UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

103 lines (85 loc) 11.6 kB
import { isSafeString, normalizeStringValue } from '../dom/normalize'; var badProtocols = ['javascript:', 'vbscript:']; var badTags = ['A', 'BODY', 'LINK', 'IMG', 'IFRAME', 'BASE', 'FORM']; var badTagsForDataURI = ['EMBED']; var badAttributes = ['href', 'src', 'background', 'action']; var badAttributesForDataURI = ['src']; function has(array, item) { return array.indexOf(item) !== -1; } function checkURI(tagName, attribute) { return (tagName === null || has(badTags, tagName)) && has(badAttributes, attribute); } function checkDataURI(tagName, attribute) { if (tagName === null) return false; return has(badTagsForDataURI, tagName) && has(badAttributesForDataURI, attribute); } export function requiresSanitization(tagName, attribute) { return checkURI(tagName, attribute) || checkDataURI(tagName, attribute); } var protocolForUrl; if (typeof URL === 'object' && URL !== null && // this is super annoying, TS thinks that URL **must** be a function so `URL.parse` check // thinks it is `never` without this `as unknown as any` typeof URL.parse === 'function') { // In Ember-land the `fastboot` package sets the `URL` global to `require('url')` // ultimately, this should be changed (so that we can either rely on the natural `URL` global // that exists) but for now we have to detect the specific `FastBoot` case first // // a future version of `fastboot` will detect if this legacy URL setup is required (by // inspecting Ember version) and if new enough, it will avoid shadowing the `URL` global // constructor with `require('url')`. var nodeURL = URL; protocolForUrl = function protocolForUrl(url) { var protocol = null; if (typeof url === 'string') { protocol = nodeURL.parse(url).protocol; } return protocol === null ? ':' : protocol; }; } else if (typeof URL === 'function') { protocolForUrl = function protocolForUrl(_url) { try { var url = new URL(_url); return url.protocol; } catch (error) { // any non-fully qualified url string will trigger an error (because there is no // baseURI that we can provide; in that case we **know** that the protocol is // "safe" because it isn't specifically one of the `badProtocols` listed above // (and those protocols can never be the default baseURI) return ':'; } }; } else { // fallback for IE11 support var parsingNode = document.createElement('a'); protocolForUrl = function protocolForUrl(url) { parsingNode.href = url; return parsingNode.protocol; }; } export function sanitizeAttributeValue(element, attribute, value) { var tagName = null; if (value === null || value === undefined) { return value; } if (isSafeString(value)) { return value.toHTML(); } if (!element) { tagName = null; } else { tagName = element.tagName.toUpperCase(); } var str = normalizeStringValue(value); if (checkURI(tagName, attribute)) { var protocol = protocolForUrl(str); if (has(badProtocols, protocol)) { return "unsafe:" + str; } } if (checkDataURI(tagName, attribute)) { return "unsafe:" + str; } return str; } //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL2RvbS9zYW5pdGl6ZWQtdmFsdWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLFNBQUEsWUFBQSxFQUFBLG9CQUFBLFFBQUEsa0JBQUE7QUFFQSxJQUFNLFlBQVksR0FBRyxDQUFBLGFBQUEsRUFBckIsV0FBcUIsQ0FBckI7QUFFQSxJQUFNLE9BQU8sR0FBRyxDQUFBLEdBQUEsRUFBQSxNQUFBLEVBQUEsTUFBQSxFQUFBLEtBQUEsRUFBQSxRQUFBLEVBQUEsTUFBQSxFQUFoQixNQUFnQixDQUFoQjtBQUVBLElBQU0saUJBQWlCLEdBQUcsQ0FBMUIsT0FBMEIsQ0FBMUI7QUFFQSxJQUFNLGFBQWEsR0FBRyxDQUFBLE1BQUEsRUFBQSxLQUFBLEVBQUEsWUFBQSxFQUF0QixRQUFzQixDQUF0QjtBQUVBLElBQU0sdUJBQXVCLEdBQUcsQ0FBaEMsS0FBZ0MsQ0FBaEM7O0FBRUEsU0FBQSxHQUFBLENBQUEsS0FBQSxFQUFBLElBQUEsRUFBK0M7QUFDN0MsU0FBTyxLQUFLLENBQUwsT0FBQSxDQUFBLElBQUEsTUFBd0IsQ0FBL0IsQ0FBQTtBQUNEOztBQUVELFNBQUEsUUFBQSxDQUFBLE9BQUEsRUFBQSxTQUFBLEVBQTREO0FBQzFELFNBQU8sQ0FBQyxPQUFPLEtBQVAsSUFBQSxJQUFvQixHQUFHLENBQUEsT0FBQSxFQUF4QixPQUF3QixDQUF4QixLQUErQyxHQUFHLENBQUEsYUFBQSxFQUF6RCxTQUF5RCxDQUF6RDtBQUNEOztBQUVELFNBQUEsWUFBQSxDQUFBLE9BQUEsRUFBQSxTQUFBLEVBQWdFO0FBQzlELE1BQUksT0FBTyxLQUFYLElBQUEsRUFBc0IsT0FBQSxLQUFBO0FBQ3RCLFNBQU8sR0FBRyxDQUFBLGlCQUFBLEVBQUgsT0FBRyxDQUFILElBQW1DLEdBQUcsQ0FBQSx1QkFBQSxFQUE3QyxTQUE2QyxDQUE3QztBQUNEOztBQUVELE9BQU0sU0FBQSxvQkFBQSxDQUFBLE9BQUEsRUFBQSxTQUFBLEVBQWlFO0FBQ3JFLFNBQU8sUUFBUSxDQUFBLE9BQUEsRUFBUixTQUFRLENBQVIsSUFBZ0MsWUFBWSxDQUFBLE9BQUEsRUFBbkQsU0FBbUQsQ0FBbkQ7QUFDRDtBQVVELElBQUEsY0FBQTs7QUFFQSxJQUNFLE9BQUEsR0FBQSxLQUFBLFFBQUEsSUFDQSxHQUFHLEtBREgsSUFBQSxJQUVBO0FBQ0E7QUFDQSxPQUFTLEdBQXVCLENBQWhDLEtBQUEsS0FMRixVQUFBLEVBTUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUksT0FBTyxHQUFYLEdBQUE7O0FBRUEsRUFBQSxjQUFjLEdBQUksd0JBQUEsR0FBRCxFQUFnQjtBQUMvQixRQUFJLFFBQVEsR0FBWixJQUFBOztBQUVBLFFBQUksT0FBQSxHQUFBLEtBQUosUUFBQSxFQUE2QjtBQUMzQixNQUFBLFFBQVEsR0FBRyxPQUFPLENBQVAsS0FBQSxDQUFBLEdBQUEsRUFBWCxRQUFBO0FBQ0Q7O0FBRUQsV0FBTyxRQUFRLEtBQVIsSUFBQSxHQUFBLEdBQUEsR0FBUCxRQUFBO0FBUEYsR0FBQTtBQWhCRixDQUFBLE1BeUJPLElBQUksT0FBQSxHQUFBLEtBQUosVUFBQSxFQUErQjtBQUNwQyxFQUFBLGNBQWMsR0FBSSx3QkFBQSxJQUFELEVBQWlCO0FBQ2hDLFFBQUk7QUFDRixVQUFJLEdBQUcsR0FBRyxJQUFBLEdBQUEsQ0FBVixJQUFVLENBQVY7QUFFQSxhQUFPLEdBQUcsQ0FBVixRQUFBO0FBSEYsS0FBQSxDQUlFLE9BQUEsS0FBQSxFQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFBLEdBQUE7QUFDRDtBQVhILEdBQUE7QUFESyxDQUFBLE1BY0E7QUFDTDtBQUNBLE1BQUksV0FBVyxHQUFHLFFBQVEsQ0FBUixhQUFBLENBQWxCLEdBQWtCLENBQWxCOztBQUVBLEVBQUEsY0FBYyxHQUFJLHdCQUFBLEdBQUQsRUFBZ0I7QUFDL0IsSUFBQSxXQUFXLENBQVgsSUFBQSxHQUFBLEdBQUE7QUFDQSxXQUFPLFdBQVcsQ0FBbEIsUUFBQTtBQUZGLEdBQUE7QUFJRDs7QUFFRCxPQUFNLFNBQUEsc0JBQUEsQ0FBQSxPQUFBLEVBQUEsU0FBQSxFQUFBLEtBQUEsRUFHVTtBQUVkLE1BQUksT0FBTyxHQUFYLElBQUE7O0FBRUEsTUFBSSxLQUFLLEtBQUwsSUFBQSxJQUFrQixLQUFLLEtBQTNCLFNBQUEsRUFBMkM7QUFDekMsV0FBQSxLQUFBO0FBQ0Q7O0FBRUQsTUFBSSxZQUFZLENBQWhCLEtBQWdCLENBQWhCLEVBQXlCO0FBQ3ZCLFdBQU8sS0FBSyxDQUFaLE1BQU8sRUFBUDtBQUNEOztBQUVELE1BQUksQ0FBSixPQUFBLEVBQWM7QUFDWixJQUFBLE9BQU8sR0FBUCxJQUFBO0FBREYsR0FBQSxNQUVPO0FBQ0wsSUFBQSxPQUFPLEdBQUcsT0FBTyxDQUFQLE9BQUEsQ0FBVixXQUFVLEVBQVY7QUFDRDs7QUFFRCxNQUFJLEdBQUcsR0FBRyxvQkFBb0IsQ0FBOUIsS0FBOEIsQ0FBOUI7O0FBRUEsTUFBSSxRQUFRLENBQUEsT0FBQSxFQUFaLFNBQVksQ0FBWixFQUFrQztBQUNoQyxRQUFJLFFBQVEsR0FBRyxjQUFjLENBQTdCLEdBQTZCLENBQTdCOztBQUNBLFFBQUksR0FBRyxDQUFBLFlBQUEsRUFBUCxRQUFPLENBQVAsRUFBaUM7QUFDL0IseUJBQUEsR0FBQTtBQUNEO0FBQ0Y7O0FBRUQsTUFBSSxZQUFZLENBQUEsT0FBQSxFQUFoQixTQUFnQixDQUFoQixFQUFzQztBQUNwQyx1QkFBQSxHQUFBO0FBQ0Q7O0FBRUQsU0FBQSxHQUFBO0FBQ0QiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBPcHRpb24gfSBmcm9tICdAZ2xpbW1lci9pbnRlcmZhY2VzJztcbmltcG9ydCB7IFNpbXBsZUVsZW1lbnQgfSBmcm9tICdAc2ltcGxlLWRvbS9pbnRlcmZhY2UnO1xuaW1wb3J0IHsgaXNTYWZlU3RyaW5nLCBub3JtYWxpemVTdHJpbmdWYWx1ZSB9IGZyb20gJy4uL2RvbS9ub3JtYWxpemUnO1xuXG5jb25zdCBiYWRQcm90b2NvbHMgPSBbJ2phdmFzY3JpcHQ6JywgJ3Zic2NyaXB0OiddO1xuXG5jb25zdCBiYWRUYWdzID0gWydBJywgJ0JPRFknLCAnTElOSycsICdJTUcnLCAnSUZSQU1FJywgJ0JBU0UnLCAnRk9STSddO1xuXG5jb25zdCBiYWRUYWdzRm9yRGF0YVVSSSA9IFsnRU1CRUQnXTtcblxuY29uc3QgYmFkQXR0cmlidXRlcyA9IFsnaHJlZicsICdzcmMnLCAnYmFja2dyb3VuZCcsICdhY3Rpb24nXTtcblxuY29uc3QgYmFkQXR0cmlidXRlc0ZvckRhdGFVUkkgPSBbJ3NyYyddO1xuXG5mdW5jdGlvbiBoYXMoYXJyYXk6IEFycmF5PHN0cmluZz4sIGl0ZW06IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gYXJyYXkuaW5kZXhPZihpdGVtKSAhPT0gLTE7XG59XG5cbmZ1bmN0aW9uIGNoZWNrVVJJKHRhZ05hbWU6IE9wdGlvbjxzdHJpbmc+LCBhdHRyaWJ1dGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gKHRhZ05hbWUgPT09IG51bGwgfHwgaGFzKGJhZFRhZ3MsIHRhZ05hbWUpKSAmJiBoYXMoYmFkQXR0cmlidXRlcywgYXR0cmlidXRlKTtcbn1cblxuZnVuY3Rpb24gY2hlY2tEYXRhVVJJKHRhZ05hbWU6IE9wdGlvbjxzdHJpbmc+LCBhdHRyaWJ1dGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICBpZiAodGFnTmFtZSA9PT0gbnVsbCkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gaGFzKGJhZFRhZ3NGb3JEYXRhVVJJLCB0YWdOYW1lKSAmJiBoYXMoYmFkQXR0cmlidXRlc0ZvckRhdGFVUkksIGF0dHJpYnV0ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlc1Nhbml0aXphdGlvbih0YWdOYW1lOiBzdHJpbmcsIGF0dHJpYnV0ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBjaGVja1VSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpIHx8IGNoZWNrRGF0YVVSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpO1xufVxuXG5pbnRlcmZhY2UgTm9kZVVybFBhcnNlUmVzdWx0IHtcbiAgcHJvdG9jb2w6IHN0cmluZyB8IG51bGw7XG59XG5cbmludGVyZmFjZSBOb2RlVXJsTW9kdWxlIHtcbiAgcGFyc2UodXJsOiBzdHJpbmcpOiBOb2RlVXJsUGFyc2VSZXN1bHQ7XG59XG5cbmxldCBwcm90b2NvbEZvclVybDogKHVybDogc3RyaW5nKSA9PiBzdHJpbmc7XG5cbmlmIChcbiAgdHlwZW9mIFVSTCA9PT0gJ29iamVjdCcgJiZcbiAgVVJMICE9PSBudWxsICYmXG4gIC8vIHRoaXMgaXMgc3VwZXIgYW5ub3lpbmcsIFRTIHRoaW5rcyB0aGF0IFVSTCAqKm11c3QqKiBiZSBhIGZ1bmN0aW9uIHNvIGBVUkwucGFyc2VgIGNoZWNrXG4gIC8vIHRoaW5rcyBpdCBpcyBgbmV2ZXJgIHdpdGhvdXQgdGhpcyBgYXMgdW5rbm93biBhcyBhbnlgXG4gIHR5cGVvZiAoKFVSTCBhcyB1bmtub3duKSBhcyBhbnkpLnBhcnNlID09PSAnZnVuY3Rpb24nXG4pIHtcbiAgLy8gSW4gRW1iZXItbGFuZCB0aGUgYGZhc3Rib290YCBwYWNrYWdlIHNldHMgdGhlIGBVUkxgIGdsb2JhbCB0byBgcmVxdWlyZSgndXJsJylgXG4gIC8vIHVsdGltYXRlbHksIHRoaXMgc2hvdWxkIGJlIGNoYW5nZWQgKHNvIHRoYXQgd2UgY2FuIGVpdGhlciByZWx5IG9uIHRoZSBuYXR1cmFsIGBVUkxgIGdsb2JhbFxuICAvLyB0aGF0IGV4aXN0cykgYnV0IGZvciBub3cgd2UgaGF2ZSB0byBkZXRlY3QgdGhlIHNwZWNpZmljIGBGYXN0Qm9vdGAgY2FzZSBmaXJzdFxuICAvL1xuICAvLyBhIGZ1dHVyZSB2ZXJzaW9uIG9mIGBmYXN0Ym9vdGAgd2lsbCBkZXRlY3QgaWYgdGhpcyBsZWdhY3kgVVJMIHNldHVwIGlzIHJlcXVpcmVkIChieVxuICAvLyBpbnNwZWN0aW5nIEVtYmVyIHZlcnNpb24pIGFuZCBpZiBuZXcgZW5vdWdoLCBpdCB3aWxsIGF2b2lkIHNoYWRvd2luZyB0aGUgYFVSTGAgZ2xvYmFsXG4gIC8vIGNvbnN0cnVjdG9yIHdpdGggYHJlcXVpcmUoJ3VybCcpYC5cbiAgbGV0IG5vZGVVUkwgPSBVUkwgYXMgTm9kZVVybE1vZHVsZTtcblxuICBwcm90b2NvbEZvclVybCA9ICh1cmw6IHN0cmluZykgPT4ge1xuICAgIGxldCBwcm90b2NvbCA9IG51bGw7XG5cbiAgICBpZiAodHlwZW9mIHVybCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIHByb3RvY29sID0gbm9kZVVSTC5wYXJzZSh1cmwpLnByb3RvY29sO1xuICAgIH1cblxuICAgIHJldHVybiBwcm90b2NvbCA9PT0gbnVsbCA/ICc6JyA6IHByb3RvY29sO1xuICB9O1xufSBlbHNlIGlmICh0eXBlb2YgVVJMID09PSAnZnVuY3Rpb24nKSB7XG4gIHByb3RvY29sRm9yVXJsID0gKF91cmw6IHN0cmluZykgPT4ge1xuICAgIHRyeSB7XG4gICAgICBsZXQgdXJsID0gbmV3IFVSTChfdXJsKTtcblxuICAgICAgcmV0dXJuIHVybC5wcm90b2NvbDtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gYW55IG5vbi1mdWxseSBxdWFsaWZpZWQgdXJsIHN0cmluZyB3aWxsIHRyaWdnZXIgYW4gZXJyb3IgKGJlY2F1c2UgdGhlcmUgaXMgbm9cbiAgICAgIC8vIGJhc2VVUkkgdGhhdCB3ZSBjYW4gcHJvdmlkZTsgaW4gdGhhdCBjYXNlIHdlICoqa25vdyoqIHRoYXQgdGhlIHByb3RvY29sIGlzXG4gICAgICAvLyBcInNhZmVcIiBiZWNhdXNlIGl0IGlzbid0IHNwZWNpZmljYWxseSBvbmUgb2YgdGhlIGBiYWRQcm90b2NvbHNgIGxpc3RlZCBhYm92ZVxuICAgICAgLy8gKGFuZCB0aG9zZSBwcm90b2NvbHMgY2FuIG5ldmVyIGJlIHRoZSBkZWZhdWx0IGJhc2VVUkkpXG4gICAgICByZXR1cm4gJzonO1xuICAgIH1cbiAgfTtcbn0gZWxzZSB7XG4gIC8vIGZhbGxiYWNrIGZvciBJRTExIHN1cHBvcnRcbiAgbGV0IHBhcnNpbmdOb2RlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYScpO1xuXG4gIHByb3RvY29sRm9yVXJsID0gKHVybDogc3RyaW5nKSA9PiB7XG4gICAgcGFyc2luZ05vZGUuaHJlZiA9IHVybDtcbiAgICByZXR1cm4gcGFyc2luZ05vZGUucHJvdG9jb2w7XG4gIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzYW5pdGl6ZUF0dHJpYnV0ZVZhbHVlKFxuICBlbGVtZW50OiBTaW1wbGVFbGVtZW50LFxuICBhdHRyaWJ1dGU6IHN0cmluZyxcbiAgdmFsdWU6IHVua25vd25cbik6IHVua25vd24ge1xuICBsZXQgdGFnTmFtZTogT3B0aW9uPHN0cmluZz4gPSBudWxsO1xuXG4gIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgaWYgKGlzU2FmZVN0cmluZyh2YWx1ZSkpIHtcbiAgICByZXR1cm4gdmFsdWUudG9IVE1MKCk7XG4gIH1cblxuICBpZiAoIWVsZW1lbnQpIHtcbiAgICB0YWdOYW1lID0gbnVsbDtcbiAgfSBlbHNlIHtcbiAgICB0YWdOYW1lID0gZWxlbWVudC50YWdOYW1lLnRvVXBwZXJDYXNlKCk7XG4gIH1cblxuICBsZXQgc3RyID0gbm9ybWFsaXplU3RyaW5nVmFsdWUodmFsdWUpO1xuXG4gIGlmIChjaGVja1VSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpKSB7XG4gICAgbGV0IHByb3RvY29sID0gcHJvdG9jb2xGb3JVcmwoc3RyKTtcbiAgICBpZiAoaGFzKGJhZFByb3RvY29scywgcHJvdG9jb2wpKSB7XG4gICAgICByZXR1cm4gYHVuc2FmZToke3N0cn1gO1xuICAgIH1cbiAgfVxuXG4gIGlmIChjaGVja0RhdGFVUkkodGFnTmFtZSwgYXR0cmlidXRlKSkge1xuICAgIHJldHVybiBgdW5zYWZlOiR7c3RyfWA7XG4gIH1cblxuICByZXR1cm4gc3RyO1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ==