UNPKG

prepack

Version:

Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.

229 lines (187 loc) 6.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createMarkupForRoot = createMarkupForRoot; exports.isCustomComponent = isCustomComponent; exports.escapeHtml = escapeHtml; exports.normalizeNode = normalizeNode; exports.convertValueToNode = convertValueToNode; exports.createHtmlEscapeHelper = createHtmlEscapeHelper; exports.createArrayHelper = createArrayHelper; exports.getNonChildrenInnerMarkup = getNonChildrenInnerMarkup; exports.quoteAttributeValueForBrowser = quoteAttributeValueForBrowser; var _parser = require("@babel/parser"); var _index = require("../../values/index.js"); var _utils = require("../utils.js"); var _invariant = _interopRequireDefault(require("../../invariant.js")); var _domConfig = require("./dom-config.js"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ // Warning: This code is experimental and might not fully work. There is no guarantee // that is up-to-date with the curent react-dom/server logic and there may also be // security holes in the string escaping because of this. const matchHtmlRegExp = /["'&<>]/; function createMarkupForRoot() { return _domConfig.ROOT_ATTRIBUTE_NAME + '=""'; } function isCustomComponent(realm, tagName, propsValue) { if (tagName.indexOf("-") === -1) { let is = (0, _utils.getProperty)(realm, propsValue, "is"); return is instanceof _index.StringValue; } switch (tagName) { case "annotation-xml": case "color-profile": case "font-face": case "font-face-src": case "font-face-uri": case "font-face-format": case "font-face-name": case "missing-glyph": return false; default: return true; } } // $FlowFixMe: we don't want to provides types here as we inject this function into source function escapeHtml(string) { if (typeof string === "boolean" || typeof string === "number") { return "" + string; } let str = "" + string; let match = matchHtmlRegExp.exec(str); if (!match) { return str; } let escape; let html = ""; let index = 0; let lastIndex = 0; for (index = match.index; index < str.length; index++) { switch (str.charCodeAt(index)) { case 34: escape = "&quot;"; break; case 38: escape = "&amp;"; break; case 39: escape = "&#x27;"; break; case 60: escape = "&lt;"; break; case 62: escape = "&gt;"; break; default: continue; } if (lastIndex !== index) { html += str.substring(lastIndex, index); } lastIndex = index + 1; html += escape; } return lastIndex !== index ? html + str.substring(lastIndex, index) : html; } function normalizeNode(realm, reactNode) { if (Array.isArray(reactNode)) { let newReactNode; for (let element of reactNode) { if (typeof element === "string") { if (newReactNode === undefined) { newReactNode = element; } else if (typeof newReactNode === "string") { newReactNode += element; } else { let lastNode = newReactNode[newReactNode.length - 1]; if (typeof lastNode === "string") { newReactNode[newReactNode.length - 1] += element; } else { newReactNode.push(element); } } } else if (newReactNode === undefined) { newReactNode = [element]; } else if (typeof newReactNode === "string") { newReactNode = [newReactNode, element]; } else { newReactNode.push(element); } } (0, _invariant.default)(newReactNode !== undefined); return newReactNode; } else if (typeof reactNode === "string" || reactNode instanceof _index.AbstractValue) { return reactNode; } (0, _invariant.default)(false, "TODO"); } function convertValueToNode(value) { if (value instanceof _index.AbstractValue) { return value; } else if (value instanceof _index.StringValue || value instanceof _index.NumberValue) { return value.value + ""; } (0, _invariant.default)(false, "TODO"); } function createHtmlEscapeHelper(realm) { let escapeHelperAst = (0, _parser.parseExpression)(escapeHtml.toString(), { plugins: ["flow"] }); let helper = new _index.ECMAScriptSourceFunctionValue(realm); helper.initialize(escapeHelperAst.params, escapeHelperAst.body); return helper; } function createArrayHelper(realm) { let arrayHelper = ` function arrayHelper(array) { let length = array.length; let i = 0; let str = ""; let item; while (i < length) { item = array[i++]; if (previousWasTextNode === true) { str += "<!-- -->" + item; } else { str += item; } previousWasTextNode = item[0] !== "<"; } return str; } `; let escapeHelperAst = (0, _parser.parseExpression)(arrayHelper, { plugins: ["flow"] }); let helper = new _index.ECMAScriptSourceFunctionValue(realm); helper.initialize(escapeHelperAst.params, escapeHelperAst.body); return helper; } function getNonChildrenInnerMarkup(realm, propsValue) { let innerHTML = (0, _utils.getProperty)(realm, propsValue, "dangerouslySetInnerHTML"); if (innerHTML instanceof _index.ObjectValue) { let _html = (0, _utils.getProperty)(realm, innerHTML, "dangerouslySetInnerHTML"); if (_html instanceof _index.StringValue) { return _html.value; } } else { let content = (0, _utils.getProperty)(realm, propsValue, "children"); if (content instanceof _index.StringValue || content instanceof _index.NumberValue) { return escapeHtml(content.value); } } return null; } function quoteAttributeValueForBrowser(value) { return '"' + escapeHtml(value) + '"'; } //# sourceMappingURL=utils.js.map