UNPKG

@glimmer/runtime

Version:

Minimal runtime needed to render Glimmer templates

103 lines (85 loc) 11.6 kB
import { isSafeString, normalizeStringValue } from '../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); } export 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; }; } export function sanitizeAttributeValue(element, attribute, value) { let tagName = null; if (value === null || value === undefined) { return value; } if (isSafeString(value)) { return value.toHTML(); } if (!element) { tagName = null; } else { tagName = element.tagName.toUpperCase(); } let str = 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,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL0BnbGltbWVyL3J1bnRpbWUvbGliL2RvbS9zYW5pdGl6ZWQtdmFsdWVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLFNBQVMsWUFBVCxFQUF1QixvQkFBdkIsUUFBbUQsa0JBQW5EO0FBRUEsTUFBTSxZQUFZLEdBQUcsQ0FBQyxhQUFELEVBQWdCLFdBQWhCLENBQXJCO0FBRUEsTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFELEVBQU0sTUFBTixFQUFjLE1BQWQsRUFBc0IsS0FBdEIsRUFBNkIsUUFBN0IsRUFBdUMsTUFBdkMsRUFBK0MsTUFBL0MsQ0FBaEI7QUFFQSxNQUFNLGlCQUFpQixHQUFHLENBQUMsT0FBRCxDQUExQjtBQUVBLE1BQU0sYUFBYSxHQUFHLENBQUMsTUFBRCxFQUFTLEtBQVQsRUFBZ0IsWUFBaEIsRUFBOEIsUUFBOUIsQ0FBdEI7QUFFQSxNQUFNLHVCQUF1QixHQUFHLENBQUMsS0FBRCxDQUFoQzs7QUFFQSxTQUFTLEdBQVQsQ0FBYSxLQUFiLEVBQW1DLElBQW5DLEVBQStDO0FBQzdDLFNBQU8sS0FBSyxDQUFDLE9BQU4sQ0FBYyxJQUFkLE1BQXdCLENBQUMsQ0FBaEM7QUFDRDs7QUFFRCxTQUFTLFFBQVQsQ0FBa0IsT0FBbEIsRUFBMkMsU0FBM0MsRUFBNEQ7QUFDMUQsU0FBTyxDQUFDLE9BQU8sS0FBSyxJQUFaLElBQW9CLEdBQUcsQ0FBQyxPQUFELEVBQVUsT0FBVixDQUF4QixLQUErQyxHQUFHLENBQUMsYUFBRCxFQUFnQixTQUFoQixDQUF6RDtBQUNEOztBQUVELFNBQVMsWUFBVCxDQUFzQixPQUF0QixFQUErQyxTQUEvQyxFQUFnRTtBQUM5RCxNQUFJLE9BQU8sS0FBSyxJQUFoQixFQUFzQixPQUFPLEtBQVA7QUFDdEIsU0FBTyxHQUFHLENBQUMsaUJBQUQsRUFBb0IsT0FBcEIsQ0FBSCxJQUFtQyxHQUFHLENBQUMsdUJBQUQsRUFBMEIsU0FBMUIsQ0FBN0M7QUFDRDs7QUFFRCxPQUFNLFNBQVUsb0JBQVYsQ0FBK0IsT0FBL0IsRUFBZ0QsU0FBaEQsRUFBaUU7QUFDckUsU0FBTyxRQUFRLENBQUMsT0FBRCxFQUFVLFNBQVYsQ0FBUixJQUFnQyxZQUFZLENBQUMsT0FBRCxFQUFVLFNBQVYsQ0FBbkQ7QUFDRDtBQVVELElBQUksY0FBSjs7QUFFQSxJQUNFLE9BQU8sR0FBUCxLQUFlLFFBQWYsSUFDQSxHQUFHLEtBQUssSUFEUixJQUVBO0FBQ0E7QUFDQSxPQUFTLEdBQXVCLENBQUMsS0FBakMsS0FBMkMsVUFMN0MsRUFNRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBSSxPQUFPLEdBQUcsR0FBZDs7QUFFQSxFQUFBLGNBQWMsR0FBSSxHQUFELElBQWdCO0FBQy9CLFFBQUksUUFBUSxHQUFHLElBQWY7O0FBRUEsUUFBSSxPQUFPLEdBQVAsS0FBZSxRQUFuQixFQUE2QjtBQUMzQixNQUFBLFFBQVEsR0FBRyxPQUFPLENBQUMsS0FBUixDQUFjLEdBQWQsRUFBbUIsUUFBOUI7QUFDRDs7QUFFRCxXQUFPLFFBQVEsS0FBSyxJQUFiLEdBQW9CLEdBQXBCLEdBQTBCLFFBQWpDO0FBQ0QsR0FSRDtBQVNELENBekJELE1BeUJPLElBQUksT0FBTyxHQUFQLEtBQWUsVUFBbkIsRUFBK0I7QUFDcEMsRUFBQSxjQUFjLEdBQUksSUFBRCxJQUFpQjtBQUNoQyxRQUFJO0FBQ0YsVUFBSSxHQUFHLEdBQUcsSUFBSSxHQUFKLENBQVEsSUFBUixDQUFWO0FBRUEsYUFBTyxHQUFHLENBQUMsUUFBWDtBQUNELEtBSkQsQ0FJRSxPQUFPLEtBQVAsRUFBYztBQUNkO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBTyxHQUFQO0FBQ0Q7QUFDRixHQVpEO0FBYUQsQ0FkTSxNQWNBO0FBQ0w7QUFDQSxNQUFJLFdBQVcsR0FBRyxRQUFRLENBQUMsYUFBVCxDQUF1QixHQUF2QixDQUFsQjs7QUFFQSxFQUFBLGNBQWMsR0FBSSxHQUFELElBQWdCO0FBQy9CLElBQUEsV0FBVyxDQUFDLElBQVosR0FBbUIsR0FBbkI7QUFDQSxXQUFPLFdBQVcsQ0FBQyxRQUFuQjtBQUNELEdBSEQ7QUFJRDs7QUFFRCxPQUFNLFNBQVUsc0JBQVYsQ0FDSixPQURJLEVBRUosU0FGSSxFQUdKLEtBSEksRUFHVTtBQUVkLE1BQUksT0FBTyxHQUFtQixJQUE5Qjs7QUFFQSxNQUFJLEtBQUssS0FBSyxJQUFWLElBQWtCLEtBQUssS0FBSyxTQUFoQyxFQUEyQztBQUN6QyxXQUFPLEtBQVA7QUFDRDs7QUFFRCxNQUFJLFlBQVksQ0FBQyxLQUFELENBQWhCLEVBQXlCO0FBQ3ZCLFdBQU8sS0FBSyxDQUFDLE1BQU4sRUFBUDtBQUNEOztBQUVELE1BQUksQ0FBQyxPQUFMLEVBQWM7QUFDWixJQUFBLE9BQU8sR0FBRyxJQUFWO0FBQ0QsR0FGRCxNQUVPO0FBQ0wsSUFBQSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQVIsQ0FBZ0IsV0FBaEIsRUFBVjtBQUNEOztBQUVELE1BQUksR0FBRyxHQUFHLG9CQUFvQixDQUFDLEtBQUQsQ0FBOUI7O0FBRUEsTUFBSSxRQUFRLENBQUMsT0FBRCxFQUFVLFNBQVYsQ0FBWixFQUFrQztBQUNoQyxRQUFJLFFBQVEsR0FBRyxjQUFjLENBQUMsR0FBRCxDQUE3Qjs7QUFDQSxRQUFJLEdBQUcsQ0FBQyxZQUFELEVBQWUsUUFBZixDQUFQLEVBQWlDO0FBQy9CLGFBQU8sVUFBVSxHQUFHLEVBQXBCO0FBQ0Q7QUFDRjs7QUFFRCxNQUFJLFlBQVksQ0FBQyxPQUFELEVBQVUsU0FBVixDQUFoQixFQUFzQztBQUNwQyxXQUFPLFVBQVUsR0FBRyxFQUFwQjtBQUNEOztBQUVELFNBQU8sR0FBUDtBQUNEIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgT3B0aW9uIH0gZnJvbSAnQGdsaW1tZXIvaW50ZXJmYWNlcyc7XG5pbXBvcnQgeyBTaW1wbGVFbGVtZW50IH0gZnJvbSAnQHNpbXBsZS1kb20vaW50ZXJmYWNlJztcbmltcG9ydCB7IGlzU2FmZVN0cmluZywgbm9ybWFsaXplU3RyaW5nVmFsdWUgfSBmcm9tICcuLi9kb20vbm9ybWFsaXplJztcblxuY29uc3QgYmFkUHJvdG9jb2xzID0gWydqYXZhc2NyaXB0OicsICd2YnNjcmlwdDonXTtcblxuY29uc3QgYmFkVGFncyA9IFsnQScsICdCT0RZJywgJ0xJTksnLCAnSU1HJywgJ0lGUkFNRScsICdCQVNFJywgJ0ZPUk0nXTtcblxuY29uc3QgYmFkVGFnc0ZvckRhdGFVUkkgPSBbJ0VNQkVEJ107XG5cbmNvbnN0IGJhZEF0dHJpYnV0ZXMgPSBbJ2hyZWYnLCAnc3JjJywgJ2JhY2tncm91bmQnLCAnYWN0aW9uJ107XG5cbmNvbnN0IGJhZEF0dHJpYnV0ZXNGb3JEYXRhVVJJID0gWydzcmMnXTtcblxuZnVuY3Rpb24gaGFzKGFycmF5OiBBcnJheTxzdHJpbmc+LCBpdGVtOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIGFycmF5LmluZGV4T2YoaXRlbSkgIT09IC0xO1xufVxuXG5mdW5jdGlvbiBjaGVja1VSSSh0YWdOYW1lOiBPcHRpb248c3RyaW5nPiwgYXR0cmlidXRlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuICh0YWdOYW1lID09PSBudWxsIHx8IGhhcyhiYWRUYWdzLCB0YWdOYW1lKSkgJiYgaGFzKGJhZEF0dHJpYnV0ZXMsIGF0dHJpYnV0ZSk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrRGF0YVVSSSh0YWdOYW1lOiBPcHRpb248c3RyaW5nPiwgYXR0cmlidXRlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgaWYgKHRhZ05hbWUgPT09IG51bGwpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIGhhcyhiYWRUYWdzRm9yRGF0YVVSSSwgdGFnTmFtZSkgJiYgaGFzKGJhZEF0dHJpYnV0ZXNGb3JEYXRhVVJJLCBhdHRyaWJ1dGUpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZXNTYW5pdGl6YXRpb24odGFnTmFtZTogc3RyaW5nLCBhdHRyaWJ1dGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gY2hlY2tVUkkodGFnTmFtZSwgYXR0cmlidXRlKSB8fCBjaGVja0RhdGFVUkkodGFnTmFtZSwgYXR0cmlidXRlKTtcbn1cblxuaW50ZXJmYWNlIE5vZGVVcmxQYXJzZVJlc3VsdCB7XG4gIHByb3RvY29sOiBzdHJpbmcgfCBudWxsO1xufVxuXG5pbnRlcmZhY2UgTm9kZVVybE1vZHVsZSB7XG4gIHBhcnNlKHVybDogc3RyaW5nKTogTm9kZVVybFBhcnNlUmVzdWx0O1xufVxuXG5sZXQgcHJvdG9jb2xGb3JVcmw6ICh1cmw6IHN0cmluZykgPT4gc3RyaW5nO1xuXG5pZiAoXG4gIHR5cGVvZiBVUkwgPT09ICdvYmplY3QnICYmXG4gIFVSTCAhPT0gbnVsbCAmJlxuICAvLyB0aGlzIGlzIHN1cGVyIGFubm95aW5nLCBUUyB0aGlua3MgdGhhdCBVUkwgKiptdXN0KiogYmUgYSBmdW5jdGlvbiBzbyBgVVJMLnBhcnNlYCBjaGVja1xuICAvLyB0aGlua3MgaXQgaXMgYG5ldmVyYCB3aXRob3V0IHRoaXMgYGFzIHVua25vd24gYXMgYW55YFxuICB0eXBlb2YgKChVUkwgYXMgdW5rbm93bikgYXMgYW55KS5wYXJzZSA9PT0gJ2Z1bmN0aW9uJ1xuKSB7XG4gIC8vIEluIEVtYmVyLWxhbmQgdGhlIGBmYXN0Ym9vdGAgcGFja2FnZSBzZXRzIHRoZSBgVVJMYCBnbG9iYWwgdG8gYHJlcXVpcmUoJ3VybCcpYFxuICAvLyB1bHRpbWF0ZWx5LCB0aGlzIHNob3VsZCBiZSBjaGFuZ2VkIChzbyB0aGF0IHdlIGNhbiBlaXRoZXIgcmVseSBvbiB0aGUgbmF0dXJhbCBgVVJMYCBnbG9iYWxcbiAgLy8gdGhhdCBleGlzdHMpIGJ1dCBmb3Igbm93IHdlIGhhdmUgdG8gZGV0ZWN0IHRoZSBzcGVjaWZpYyBgRmFzdEJvb3RgIGNhc2UgZmlyc3RcbiAgLy9cbiAgLy8gYSBmdXR1cmUgdmVyc2lvbiBvZiBgZmFzdGJvb3RgIHdpbGwgZGV0ZWN0IGlmIHRoaXMgbGVnYWN5IFVSTCBzZXR1cCBpcyByZXF1aXJlZCAoYnlcbiAgLy8gaW5zcGVjdGluZyBFbWJlciB2ZXJzaW9uKSBhbmQgaWYgbmV3IGVub3VnaCwgaXQgd2lsbCBhdm9pZCBzaGFkb3dpbmcgdGhlIGBVUkxgIGdsb2JhbFxuICAvLyBjb25zdHJ1Y3RvciB3aXRoIGByZXF1aXJlKCd1cmwnKWAuXG4gIGxldCBub2RlVVJMID0gVVJMIGFzIE5vZGVVcmxNb2R1bGU7XG5cbiAgcHJvdG9jb2xGb3JVcmwgPSAodXJsOiBzdHJpbmcpID0+IHtcbiAgICBsZXQgcHJvdG9jb2wgPSBudWxsO1xuXG4gICAgaWYgKHR5cGVvZiB1cmwgPT09ICdzdHJpbmcnKSB7XG4gICAgICBwcm90b2NvbCA9IG5vZGVVUkwucGFyc2UodXJsKS5wcm90b2NvbDtcbiAgICB9XG5cbiAgICByZXR1cm4gcHJvdG9jb2wgPT09IG51bGwgPyAnOicgOiBwcm90b2NvbDtcbiAgfTtcbn0gZWxzZSBpZiAodHlwZW9mIFVSTCA9PT0gJ2Z1bmN0aW9uJykge1xuICBwcm90b2NvbEZvclVybCA9IChfdXJsOiBzdHJpbmcpID0+IHtcbiAgICB0cnkge1xuICAgICAgbGV0IHVybCA9IG5ldyBVUkwoX3VybCk7XG5cbiAgICAgIHJldHVybiB1cmwucHJvdG9jb2w7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIC8vIGFueSBub24tZnVsbHkgcXVhbGlmaWVkIHVybCBzdHJpbmcgd2lsbCB0cmlnZ2VyIGFuIGVycm9yIChiZWNhdXNlIHRoZXJlIGlzIG5vXG4gICAgICAvLyBiYXNlVVJJIHRoYXQgd2UgY2FuIHByb3ZpZGU7IGluIHRoYXQgY2FzZSB3ZSAqKmtub3cqKiB0aGF0IHRoZSBwcm90b2NvbCBpc1xuICAgICAgLy8gXCJzYWZlXCIgYmVjYXVzZSBpdCBpc24ndCBzcGVjaWZpY2FsbHkgb25lIG9mIHRoZSBgYmFkUHJvdG9jb2xzYCBsaXN0ZWQgYWJvdmVcbiAgICAgIC8vIChhbmQgdGhvc2UgcHJvdG9jb2xzIGNhbiBuZXZlciBiZSB0aGUgZGVmYXVsdCBiYXNlVVJJKVxuICAgICAgcmV0dXJuICc6JztcbiAgICB9XG4gIH07XG59IGVsc2Uge1xuICAvLyBmYWxsYmFjayBmb3IgSUUxMSBzdXBwb3J0XG4gIGxldCBwYXJzaW5nTm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2EnKTtcblxuICBwcm90b2NvbEZvclVybCA9ICh1cmw6IHN0cmluZykgPT4ge1xuICAgIHBhcnNpbmdOb2RlLmhyZWYgPSB1cmw7XG4gICAgcmV0dXJuIHBhcnNpbmdOb2RlLnByb3RvY29sO1xuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2FuaXRpemVBdHRyaWJ1dGVWYWx1ZShcbiAgZWxlbWVudDogU2ltcGxlRWxlbWVudCxcbiAgYXR0cmlidXRlOiBzdHJpbmcsXG4gIHZhbHVlOiB1bmtub3duXG4pOiB1bmtub3duIHtcbiAgbGV0IHRhZ05hbWU6IE9wdGlvbjxzdHJpbmc+ID0gbnVsbDtcblxuICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgIHJldHVybiB2YWx1ZTtcbiAgfVxuXG4gIGlmIChpc1NhZmVTdHJpbmcodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlLnRvSFRNTCgpO1xuICB9XG5cbiAgaWYgKCFlbGVtZW50KSB7XG4gICAgdGFnTmFtZSA9IG51bGw7XG4gIH0gZWxzZSB7XG4gICAgdGFnTmFtZSA9IGVsZW1lbnQudGFnTmFtZS50b1VwcGVyQ2FzZSgpO1xuICB9XG5cbiAgbGV0IHN0ciA9IG5vcm1hbGl6ZVN0cmluZ1ZhbHVlKHZhbHVlKTtcblxuICBpZiAoY2hlY2tVUkkodGFnTmFtZSwgYXR0cmlidXRlKSkge1xuICAgIGxldCBwcm90b2NvbCA9IHByb3RvY29sRm9yVXJsKHN0cik7XG4gICAgaWYgKGhhcyhiYWRQcm90b2NvbHMsIHByb3RvY29sKSkge1xuICAgICAgcmV0dXJuIGB1bnNhZmU6JHtzdHJ9YDtcbiAgICB9XG4gIH1cblxuICBpZiAoY2hlY2tEYXRhVVJJKHRhZ05hbWUsIGF0dHJpYnV0ZSkpIHtcbiAgICByZXR1cm4gYHVuc2FmZToke3N0cn1gO1xuICB9XG5cbiAgcmV0dXJuIHN0cjtcbn1cbiJdLCJzb3VyY2VSb290IjoiIn0=