@glimmer/runtime
Version:
Minimal runtime needed to render Glimmer templates
113 lines (91 loc) • 11.7 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.requiresSanitization = requiresSanitization;
exports.sanitizeAttributeValue = sanitizeAttributeValue;
var _normalize = require("../dom/normalize");
const badProtocols = ['javascript:', 'vbscript:'];
const badTags = ['A', 'BODY', 'LINK', 'IMG', 'IFRAME', 'BASE', 'FORM'];
const badTagsForDataURI = ['EMBED'];
const badAttributes = ['href', 'src', 'background', 'action'];
const 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);
}
function requiresSanitization(tagName, attribute) {
return checkURI(tagName, attribute) || checkDataURI(tagName, attribute);
}
let 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')`.
let nodeURL = URL;
protocolForUrl = url => {
let protocol = null;
if (typeof url === 'string') {
protocol = nodeURL.parse(url).protocol;
}
return protocol === null ? ':' : protocol;
};
} else if (typeof URL === 'function') {
protocolForUrl = _url => {
try {
let 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
let parsingNode = document.createElement('a');
protocolForUrl = url => {
parsingNode.href = url;
return parsingNode.protocol;
};
}
function sanitizeAttributeValue(element, attribute, value) {
let tagName = null;
if (value === null || value === undefined) {
return value;
}
if ((0, _normalize.isSafeString)(value)) {
return value.toHTML();
}
if (!element) {
tagName = null;
} else {
tagName = element.tagName.toUpperCase();
}
let str = (0, _normalize.normalizeStringValue)(value);
if (checkURI(tagName, attribute)) {
let 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL2RvbS9zYW5pdGl6ZWQtdmFsdWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7O0FBRUE7O0FBRUEsTUFBTSxZQUFZLEdBQUcsQ0FBQSxhQUFBLEVBQXJCLFdBQXFCLENBQXJCO0FBRUEsTUFBTSxPQUFPLEdBQUcsQ0FBQSxHQUFBLEVBQUEsTUFBQSxFQUFBLE1BQUEsRUFBQSxLQUFBLEVBQUEsUUFBQSxFQUFBLE1BQUEsRUFBaEIsTUFBZ0IsQ0FBaEI7QUFFQSxNQUFNLGlCQUFpQixHQUFHLENBQTFCLE9BQTBCLENBQTFCO0FBRUEsTUFBTSxhQUFhLEdBQUcsQ0FBQSxNQUFBLEVBQUEsS0FBQSxFQUFBLFlBQUEsRUFBdEIsUUFBc0IsQ0FBdEI7QUFFQSxNQUFNLHVCQUF1QixHQUFHLENBQWhDLEtBQWdDLENBQWhDOztBQUVBLFNBQUEsR0FBQSxDQUFBLEtBQUEsRUFBQSxJQUFBLEVBQStDO0FBQzdDLFNBQU8sS0FBSyxDQUFMLE9BQUEsQ0FBQSxJQUFBLE1BQXdCLENBQS9CLENBQUE7QUFDRDs7QUFFRCxTQUFBLFFBQUEsQ0FBQSxPQUFBLEVBQUEsU0FBQSxFQUE0RDtBQUMxRCxTQUFPLENBQUMsT0FBTyxLQUFQLElBQUEsSUFBb0IsR0FBRyxDQUFBLE9BQUEsRUFBeEIsT0FBd0IsQ0FBeEIsS0FBK0MsR0FBRyxDQUFBLGFBQUEsRUFBekQsU0FBeUQsQ0FBekQ7QUFDRDs7QUFFRCxTQUFBLFlBQUEsQ0FBQSxPQUFBLEVBQUEsU0FBQSxFQUFnRTtBQUM5RCxNQUFJLE9BQU8sS0FBWCxJQUFBLEVBQXNCLE9BQUEsS0FBQTtBQUN0QixTQUFPLEdBQUcsQ0FBQSxpQkFBQSxFQUFILE9BQUcsQ0FBSCxJQUFtQyxHQUFHLENBQUEsdUJBQUEsRUFBN0MsU0FBNkMsQ0FBN0M7QUFDRDs7QUFFSyxTQUFBLG9CQUFBLENBQUEsT0FBQSxFQUFBLFNBQUEsRUFBaUU7QUFDckUsU0FBTyxRQUFRLENBQUEsT0FBQSxFQUFSLFNBQVEsQ0FBUixJQUFnQyxZQUFZLENBQUEsT0FBQSxFQUFuRCxTQUFtRCxDQUFuRDtBQUNEOztBQVVELElBQUEsY0FBQTs7QUFFQSxJQUNFLE9BQUEsR0FBQSxLQUFBLFFBQUEsSUFDQSxHQUFHLEtBREgsSUFBQSxJQUVBO0FBQ0E7QUFDQSxPQUFTLEdBQXVCLENBQWhDLEtBQUEsS0FMRixVQUFBLEVBTUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE1BQUksT0FBTyxHQUFYLEdBQUE7O0FBRUEsRUFBQSxjQUFjLEdBQUksR0FBRCxJQUFnQjtBQUMvQixRQUFJLFFBQVEsR0FBWixJQUFBOztBQUVBLFFBQUksT0FBQSxHQUFBLEtBQUosUUFBQSxFQUE2QjtBQUMzQixNQUFBLFFBQVEsR0FBRyxPQUFPLENBQVAsS0FBQSxDQUFBLEdBQUEsRUFBWCxRQUFBO0FBQ0Q7O0FBRUQsV0FBTyxRQUFRLEtBQVIsSUFBQSxHQUFBLEdBQUEsR0FBUCxRQUFBO0FBUEYsR0FBQTtBQWhCRixDQUFBLE1BeUJPLElBQUksT0FBQSxHQUFBLEtBQUosVUFBQSxFQUErQjtBQUNwQyxFQUFBLGNBQWMsR0FBSSxJQUFELElBQWlCO0FBQ2hDLFFBQUk7QUFDRixVQUFJLEdBQUcsR0FBRyxJQUFBLEdBQUEsQ0FBVixJQUFVLENBQVY7QUFFQSxhQUFPLEdBQUcsQ0FBVixRQUFBO0FBSEYsS0FBQSxDQUlFLE9BQUEsS0FBQSxFQUFjO0FBQ2Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFBLEdBQUE7QUFDRDtBQVhILEdBQUE7QUFESyxDQUFBLE1BY0E7QUFDTDtBQUNBLE1BQUksV0FBVyxHQUFHLFFBQVEsQ0FBUixhQUFBLENBQWxCLEdBQWtCLENBQWxCOztBQUVBLEVBQUEsY0FBYyxHQUFJLEdBQUQsSUFBZ0I7QUFDL0IsSUFBQSxXQUFXLENBQVgsSUFBQSxHQUFBLEdBQUE7QUFDQSxXQUFPLFdBQVcsQ0FBbEIsUUFBQTtBQUZGLEdBQUE7QUFJRDs7QUFFSyxTQUFBLHNCQUFBLENBQUEsT0FBQSxFQUFBLFNBQUEsRUFBQSxLQUFBLEVBR1U7QUFFZCxNQUFJLE9BQU8sR0FBWCxJQUFBOztBQUVBLE1BQUksS0FBSyxLQUFMLElBQUEsSUFBa0IsS0FBSyxLQUEzQixTQUFBLEVBQTJDO0FBQ3pDLFdBQUEsS0FBQTtBQUNEOztBQUVELE1BQUksNkJBQUosS0FBSSxDQUFKLEVBQXlCO0FBQ3ZCLFdBQU8sS0FBSyxDQUFaLE1BQU8sRUFBUDtBQUNEOztBQUVELE1BQUksQ0FBSixPQUFBLEVBQWM7QUFDWixJQUFBLE9BQU8sR0FBUCxJQUFBO0FBREYsR0FBQSxNQUVPO0FBQ0wsSUFBQSxPQUFPLEdBQUcsT0FBTyxDQUFQLE9BQUEsQ0FBVixXQUFVLEVBQVY7QUFDRDs7QUFFRCxNQUFJLEdBQUcsR0FBRyxxQ0FBVixLQUFVLENBQVY7O0FBRUEsTUFBSSxRQUFRLENBQUEsT0FBQSxFQUFaLFNBQVksQ0FBWixFQUFrQztBQUNoQyxRQUFJLFFBQVEsR0FBRyxjQUFjLENBQTdCLEdBQTZCLENBQTdCOztBQUNBLFFBQUksR0FBRyxDQUFBLFlBQUEsRUFBUCxRQUFPLENBQVAsRUFBaUM7QUFDL0IsYUFBTyxVQUFVLEdBQWpCLEVBQUE7QUFDRDtBQUNGOztBQUVELE1BQUksWUFBWSxDQUFBLE9BQUEsRUFBaEIsU0FBZ0IsQ0FBaEIsRUFBc0M7QUFDcEMsV0FBTyxVQUFVLEdBQWpCLEVBQUE7QUFDRDs7QUFFRCxTQUFBLEdBQUE7QUFDRCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE9wdGlvbiB9IGZyb20gJ0BnbGltbWVyL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgU2ltcGxlRWxlbWVudCB9IGZyb20gJ0BzaW1wbGUtZG9tL2ludGVyZmFjZSc7XG5pbXBvcnQgeyBpc1NhZmVTdHJpbmcsIG5vcm1hbGl6ZVN0cmluZ1ZhbHVlIH0gZnJvbSAnLi4vZG9tL25vcm1hbGl6ZSc7XG5cbmNvbnN0IGJhZFByb3RvY29scyA9IFsnamF2YXNjcmlwdDonLCAndmJzY3JpcHQ6J107XG5cbmNvbnN0IGJhZFRhZ3MgPSBbJ0EnLCAnQk9EWScsICdMSU5LJywgJ0lNRycsICdJRlJBTUUnLCAnQkFTRScsICdGT1JNJ107XG5cbmNvbnN0IGJhZFRhZ3NGb3JEYXRhVVJJID0gWydFTUJFRCddO1xuXG5jb25zdCBiYWRBdHRyaWJ1dGVzID0gWydocmVmJywgJ3NyYycsICdiYWNrZ3JvdW5kJywgJ2FjdGlvbiddO1xuXG5jb25zdCBiYWRBdHRyaWJ1dGVzRm9yRGF0YVVSSSA9IFsnc3JjJ107XG5cbmZ1bmN0aW9uIGhhcyhhcnJheTogQXJyYXk8c3RyaW5nPiwgaXRlbTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBhcnJheS5pbmRleE9mKGl0ZW0pICE9PSAtMTtcbn1cblxuZnVuY3Rpb24gY2hlY2tVUkkodGFnTmFtZTogT3B0aW9uPHN0cmluZz4sIGF0dHJpYnV0ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiAodGFnTmFtZSA9PT0gbnVsbCB8fCBoYXMoYmFkVGFncywgdGFnTmFtZSkpICYmIGhhcyhiYWRBdHRyaWJ1dGVzLCBhdHRyaWJ1dGUpO1xufVxuXG5mdW5jdGlvbiBjaGVja0RhdGFVUkkodGFnTmFtZTogT3B0aW9uPHN0cmluZz4sIGF0dHJpYnV0ZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGlmICh0YWdOYW1lID09PSBudWxsKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiBoYXMoYmFkVGFnc0ZvckRhdGFVUkksIHRhZ05hbWUpICYmIGhhcyhiYWRBdHRyaWJ1dGVzRm9yRGF0YVVSSSwgYXR0cmlidXRlKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVzU2FuaXRpemF0aW9uKHRhZ05hbWU6IHN0cmluZywgYXR0cmlidXRlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIGNoZWNrVVJJKHRhZ05hbWUsIGF0dHJpYnV0ZSkgfHwgY2hlY2tEYXRhVVJJKHRhZ05hbWUsIGF0dHJpYnV0ZSk7XG59XG5cbmludGVyZmFjZSBOb2RlVXJsUGFyc2VSZXN1bHQge1xuICBwcm90b2NvbDogc3RyaW5nIHwgbnVsbDtcbn1cblxuaW50ZXJmYWNlIE5vZGVVcmxNb2R1bGUge1xuICBwYXJzZSh1cmw6IHN0cmluZyk6IE5vZGVVcmxQYXJzZVJlc3VsdDtcbn1cblxubGV0IHByb3RvY29sRm9yVXJsOiAodXJsOiBzdHJpbmcpID0+IHN0cmluZztcblxuaWYgKFxuICB0eXBlb2YgVVJMID09PSAnb2JqZWN0JyAmJlxuICBVUkwgIT09IG51bGwgJiZcbiAgLy8gdGhpcyBpcyBzdXBlciBhbm5veWluZywgVFMgdGhpbmtzIHRoYXQgVVJMICoqbXVzdCoqIGJlIGEgZnVuY3Rpb24gc28gYFVSTC5wYXJzZWAgY2hlY2tcbiAgLy8gdGhpbmtzIGl0IGlzIGBuZXZlcmAgd2l0aG91dCB0aGlzIGBhcyB1bmtub3duIGFzIGFueWBcbiAgdHlwZW9mICgoVVJMIGFzIHVua25vd24pIGFzIGFueSkucGFyc2UgPT09ICdmdW5jdGlvbidcbikge1xuICAvLyBJbiBFbWJlci1sYW5kIHRoZSBgZmFzdGJvb3RgIHBhY2thZ2Ugc2V0cyB0aGUgYFVSTGAgZ2xvYmFsIHRvIGByZXF1aXJlKCd1cmwnKWBcbiAgLy8gdWx0aW1hdGVseSwgdGhpcyBzaG91bGQgYmUgY2hhbmdlZCAoc28gdGhhdCB3ZSBjYW4gZWl0aGVyIHJlbHkgb24gdGhlIG5hdHVyYWwgYFVSTGAgZ2xvYmFsXG4gIC8vIHRoYXQgZXhpc3RzKSBidXQgZm9yIG5vdyB3ZSBoYXZlIHRvIGRldGVjdCB0aGUgc3BlY2lmaWMgYEZhc3RCb290YCBjYXNlIGZpcnN0XG4gIC8vXG4gIC8vIGEgZnV0dXJlIHZlcnNpb24gb2YgYGZhc3Rib290YCB3aWxsIGRldGVjdCBpZiB0aGlzIGxlZ2FjeSBVUkwgc2V0dXAgaXMgcmVxdWlyZWQgKGJ5XG4gIC8vIGluc3BlY3RpbmcgRW1iZXIgdmVyc2lvbikgYW5kIGlmIG5ldyBlbm91Z2gsIGl0IHdpbGwgYXZvaWQgc2hhZG93aW5nIHRoZSBgVVJMYCBnbG9iYWxcbiAgLy8gY29uc3RydWN0b3Igd2l0aCBgcmVxdWlyZSgndXJsJylgLlxuICBsZXQgbm9kZVVSTCA9IFVSTCBhcyBOb2RlVXJsTW9kdWxlO1xuXG4gIHByb3RvY29sRm9yVXJsID0gKHVybDogc3RyaW5nKSA9PiB7XG4gICAgbGV0IHByb3RvY29sID0gbnVsbDtcblxuICAgIGlmICh0eXBlb2YgdXJsID09PSAnc3RyaW5nJykge1xuICAgICAgcHJvdG9jb2wgPSBub2RlVVJMLnBhcnNlKHVybCkucHJvdG9jb2w7XG4gICAgfVxuXG4gICAgcmV0dXJuIHByb3RvY29sID09PSBudWxsID8gJzonIDogcHJvdG9jb2w7XG4gIH07XG59IGVsc2UgaWYgKHR5cGVvZiBVUkwgPT09ICdmdW5jdGlvbicpIHtcbiAgcHJvdG9jb2xGb3JVcmwgPSAoX3VybDogc3RyaW5nKSA9PiB7XG4gICAgdHJ5IHtcbiAgICAgIGxldCB1cmwgPSBuZXcgVVJMKF91cmwpO1xuXG4gICAgICByZXR1cm4gdXJsLnByb3RvY29sO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBhbnkgbm9uLWZ1bGx5IHF1YWxpZmllZCB1cmwgc3RyaW5nIHdpbGwgdHJpZ2dlciBhbiBlcnJvciAoYmVjYXVzZSB0aGVyZSBpcyBub1xuICAgICAgLy8gYmFzZVVSSSB0aGF0IHdlIGNhbiBwcm92aWRlOyBpbiB0aGF0IGNhc2Ugd2UgKiprbm93KiogdGhhdCB0aGUgcHJvdG9jb2wgaXNcbiAgICAgIC8vIFwic2FmZVwiIGJlY2F1c2UgaXQgaXNuJ3Qgc3BlY2lmaWNhbGx5IG9uZSBvZiB0aGUgYGJhZFByb3RvY29sc2AgbGlzdGVkIGFib3ZlXG4gICAgICAvLyAoYW5kIHRob3NlIHByb3RvY29scyBjYW4gbmV2ZXIgYmUgdGhlIGRlZmF1bHQgYmFzZVVSSSlcbiAgICAgIHJldHVybiAnOic7XG4gICAgfVxuICB9O1xufSBlbHNlIHtcbiAgLy8gZmFsbGJhY2sgZm9yIElFMTEgc3VwcG9ydFxuICBsZXQgcGFyc2luZ05vZGUgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdhJyk7XG5cbiAgcHJvdG9jb2xGb3JVcmwgPSAodXJsOiBzdHJpbmcpID0+IHtcbiAgICBwYXJzaW5nTm9kZS5ocmVmID0gdXJsO1xuICAgIHJldHVybiBwYXJzaW5nTm9kZS5wcm90b2NvbDtcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNhbml0aXplQXR0cmlidXRlVmFsdWUoXG4gIGVsZW1lbnQ6IFNpbXBsZUVsZW1lbnQsXG4gIGF0dHJpYnV0ZTogc3RyaW5nLFxuICB2YWx1ZTogdW5rbm93blxuKTogdW5rbm93biB7XG4gIGxldCB0YWdOYW1lOiBPcHRpb248c3RyaW5nPiA9IG51bGw7XG5cbiAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICByZXR1cm4gdmFsdWU7XG4gIH1cblxuICBpZiAoaXNTYWZlU3RyaW5nKHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZS50b0hUTUwoKTtcbiAgfVxuXG4gIGlmICghZWxlbWVudCkge1xuICAgIHRhZ05hbWUgPSBudWxsO1xuICB9IGVsc2Uge1xuICAgIHRhZ05hbWUgPSBlbGVtZW50LnRhZ05hbWUudG9VcHBlckNhc2UoKTtcbiAgfVxuXG4gIGxldCBzdHIgPSBub3JtYWxpemVTdHJpbmdWYWx1ZSh2YWx1ZSk7XG5cbiAgaWYgKGNoZWNrVVJJKHRhZ05hbWUsIGF0dHJpYnV0ZSkpIHtcbiAgICBsZXQgcHJvdG9jb2wgPSBwcm90b2NvbEZvclVybChzdHIpO1xuICAgIGlmIChoYXMoYmFkUHJvdG9jb2xzLCBwcm90b2NvbCkpIHtcbiAgICAgIHJldHVybiBgdW5zYWZlOiR7c3RyfWA7XG4gICAgfVxuICB9XG5cbiAgaWYgKGNoZWNrRGF0YVVSSSh0YWdOYW1lLCBhdHRyaWJ1dGUpKSB7XG4gICAgcmV0dXJuIGB1bnNhZmU6JHtzdHJ9YDtcbiAgfVxuXG4gIHJldHVybiBzdHI7XG59XG4iXSwic291cmNlUm9vdCI6IiJ9