416 lines
18 KiB
JavaScript
416 lines
18 KiB
JavaScript
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
|
|
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); /**
|
|
* 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.
|
|
*/
|
|
|
|
exports.default = function (ast, strictCode, env, realm) {
|
|
(0, _invariant2.default)(realm.react.enabled, "JSXElements can only be evaluated with the reactEnabled option");
|
|
var openingElement = ast.openingElement;
|
|
var type = evaluateJSXIdentifier(openingElement.name, strictCode, env, realm);
|
|
|
|
var _evaluateJSXAttribute = evaluateJSXAttributes(openingElement.name, openingElement.attributes, ast.children, strictCode, env, realm),
|
|
attributes = _evaluateJSXAttribute.attributes,
|
|
children = _evaluateJSXAttribute.children;
|
|
|
|
var key = attributes.get("key") || realm.intrinsics.null;
|
|
var ref = attributes.get("ref") || realm.intrinsics.null;
|
|
|
|
if (key === realm.intrinsics.undefined) {
|
|
key = realm.intrinsics.null;
|
|
}
|
|
if (ref === realm.intrinsics.undefined) {
|
|
ref = realm.intrinsics.null;
|
|
}
|
|
|
|
// React uses keys to identify nodes as they get updated through the reconcilation
|
|
// phase. Keys are used in a map and thus need to be converted to strings
|
|
if (key !== realm.intrinsics.null) {
|
|
key = (0, _BinaryExpression.computeBinary)(realm, "+", realm.intrinsics.emptyString, key);
|
|
}
|
|
var props = createReactProps(realm, type, attributes, children, env);
|
|
|
|
return createReactElement(realm, type, key, ref, props);
|
|
};
|
|
|
|
var _errors = require("../errors.js");
|
|
|
|
var _index = require("../values/index.js");
|
|
|
|
var _utils = require("../react/utils.js");
|
|
|
|
var _jsx = require("../react/jsx.js");
|
|
|
|
var _babelTypes = require("babel-types");
|
|
|
|
var t = _interopRequireWildcard(_babelTypes);
|
|
|
|
var _index2 = require("../methods/index.js");
|
|
|
|
var _singletons = require("../singletons.js");
|
|
|
|
var _invariant = require("../invariant.js");
|
|
|
|
var _invariant2 = _interopRequireDefault(_invariant);
|
|
|
|
var _BinaryExpression = require("./BinaryExpression.js");
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
|
|
|
var RESERVED_PROPS = {
|
|
key: true,
|
|
ref: true,
|
|
__self: true,
|
|
__source: true
|
|
};
|
|
|
|
// taken from Babel
|
|
function cleanJSXElementLiteralChild(child) {
|
|
var lines = child.split(/\r\n|\n|\r/);
|
|
|
|
var lastNonEmptyLine = 0;
|
|
|
|
for (var i = 0; i < lines.length; i++) {
|
|
if (lines[i].match(/[^ \t]/)) {
|
|
lastNonEmptyLine = i;
|
|
}
|
|
}
|
|
|
|
var str = "";
|
|
|
|
for (var _i = 0; _i < lines.length; _i++) {
|
|
var line = lines[_i];
|
|
|
|
var isFirstLine = _i === 0;
|
|
var isLastLine = _i === lines.length - 1;
|
|
var isLastNonEmptyLine = _i === lastNonEmptyLine;
|
|
|
|
// replace rendered whitespace tabs with spaces
|
|
var trimmedLine = line.replace(/\t/g, " ");
|
|
|
|
// trim whitespace touching a newline
|
|
if (!isFirstLine) {
|
|
trimmedLine = trimmedLine.replace(/^[ ]+/, "");
|
|
}
|
|
|
|
// trim whitespace touching an endline
|
|
if (!isLastLine) {
|
|
trimmedLine = trimmedLine.replace(/[ ]+$/, "");
|
|
}
|
|
|
|
if (trimmedLine) {
|
|
if (!isLastNonEmptyLine) {
|
|
trimmedLine += " ";
|
|
}
|
|
|
|
str += trimmedLine;
|
|
}
|
|
}
|
|
|
|
if (str) {
|
|
return str;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function evaluateJSXMemberExpression(ast, strictCode, env, realm) {
|
|
switch (ast.type) {
|
|
case "JSXIdentifier":
|
|
return _singletons.Environment.GetValue(realm, _singletons.Environment.ResolveBinding(realm, ast.name, strictCode, env));
|
|
case "JSXMemberExpression":
|
|
return _singletons.Environment.GetValue(realm, env.evaluate((0, _jsx.convertJSXExpressionToIdentifier)(ast), strictCode));
|
|
default:
|
|
(0, _invariant2.default)(false, "Unknown JSX Identifier");
|
|
}
|
|
}
|
|
|
|
function evaluateJSXIdentifier(ast, strictCode, env, realm) {
|
|
if (isTagName(ast)) {
|
|
// special cased lower-case and custom elements
|
|
return new _index.StringValue(realm, ast.name);
|
|
}
|
|
return evaluateJSXMemberExpression(ast, strictCode, env, realm);
|
|
}
|
|
|
|
function evaluateJSXValue(value, strictCode, env, realm) {
|
|
if (value != null) {
|
|
switch (value.type) {
|
|
case "JSXText":
|
|
return new _index.StringValue(realm, value.value);
|
|
case "StringLiteral":
|
|
return new _index.StringValue(realm, value.value);
|
|
case "JSXExpressionContainer":
|
|
return _singletons.Environment.GetValue(realm, env.evaluate(value.expression, strictCode));
|
|
case "JSXElement":
|
|
return _singletons.Environment.GetValue(realm, env.evaluate(value, strictCode));
|
|
default:
|
|
(0, _invariant2.default)(false, "Unknown JSX value type: " + value.type);
|
|
}
|
|
}
|
|
(0, _invariant2.default)(false, "Null or undefined value passed when trying to evaluate JSX node value");
|
|
}
|
|
|
|
function isTagName(ast) {
|
|
return ast.type === "JSXIdentifier" && /^[a-z]|\-/.test(ast.name);
|
|
}
|
|
|
|
function getDefaultProps(elementType, env, realm) {
|
|
var name = void 0;
|
|
if (elementType.type === "JSXIdentifier") {
|
|
name = elementType.name;
|
|
}
|
|
if (!isTagName(elementType) && typeof name === "string") {
|
|
// find the value of "ComponentXXX.defaultProps"
|
|
var defaultProps = _singletons.Environment.GetValue(realm, env.evaluate(t.memberExpression(t.identifier(name), t.identifier("defaultProps")), false));
|
|
|
|
if (defaultProps instanceof _index.ObjectValue) {
|
|
return defaultProps;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function evaluateJSXChildren(children, strictCode, env, realm) {
|
|
if (children.length === 0) {
|
|
return null;
|
|
}
|
|
if (children.length === 1) {
|
|
var singleChild = evaluateJSXValue(children[0], strictCode, env, realm);
|
|
|
|
if (singleChild instanceof _index.StringValue) {
|
|
var text = cleanJSXElementLiteralChild(singleChild.value);
|
|
if (text !== null) {
|
|
singleChild.value = text;
|
|
}
|
|
}
|
|
return singleChild;
|
|
}
|
|
var array = _singletons.Create.ArrayCreate(realm, 0);
|
|
var dynamicChildrenLength = children.length;
|
|
var dynamicIterator = 0;
|
|
var lastChildValue = null;
|
|
for (var i = 0; i < children.length; i++) {
|
|
var value = evaluateJSXValue(children[i], strictCode, env, realm);
|
|
if (value instanceof _index.StringValue) {
|
|
var _text = cleanJSXElementLiteralChild(value.value);
|
|
if (_text === null) {
|
|
dynamicChildrenLength--;
|
|
// this is a space full of whitespace, so let's proceed
|
|
continue;
|
|
} else {
|
|
value.value = _text;
|
|
}
|
|
}
|
|
lastChildValue = value;
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, array, "" + dynamicIterator, value);
|
|
dynamicIterator++;
|
|
}
|
|
if (dynamicChildrenLength === 1) {
|
|
return lastChildValue;
|
|
}
|
|
|
|
_singletons.Properties.Set(realm, array, "length", new _index.NumberValue(realm, dynamicChildrenLength), false);
|
|
return array;
|
|
}
|
|
|
|
function evaluateJSXAttributes(elementType, astAttributes, astChildren, strictCode, env, realm) {
|
|
var attributes = new Map();
|
|
var children = evaluateJSXChildren(astChildren, strictCode, env, realm);
|
|
var defaultProps = getDefaultProps(elementType, env, realm);
|
|
|
|
// defaultProps are a bit like default function arguments
|
|
// if an actual value exists, it should overwrite the default value
|
|
if (defaultProps !== null) {
|
|
var _iteratorNormalCompletion = true;
|
|
var _didIteratorError = false;
|
|
var _iteratorError = undefined;
|
|
|
|
try {
|
|
for (var _iterator = defaultProps.properties[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
var _ref = _step.value;
|
|
|
|
var _ref2 = _slicedToArray(_ref, 1);
|
|
|
|
var key = _ref2[0];
|
|
|
|
var defaultPropValue = (0, _index2.Get)(realm, defaultProps, key);
|
|
|
|
if (defaultPropValue instanceof _index.Value) {
|
|
if (key === "children") {
|
|
if (children === null) {
|
|
children = defaultPropValue;
|
|
}
|
|
} else {
|
|
attributes.set(key, defaultPropValue);
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError = true;
|
|
_iteratorError = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
|
_iterator.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError) {
|
|
throw _iteratorError;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
var _iteratorNormalCompletion2 = true;
|
|
var _didIteratorError2 = false;
|
|
var _iteratorError2 = undefined;
|
|
|
|
try {
|
|
for (var _iterator2 = astAttributes[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
|
var astAttribute = _step2.value;
|
|
|
|
switch (astAttribute.type) {
|
|
case "JSXAttribute":
|
|
var name = astAttribute.name,
|
|
value = astAttribute.value;
|
|
|
|
|
|
(0, _invariant2.default)(name.type === "JSXIdentifier", "JSX attribute name type not supported: " + astAttribute.type);
|
|
attributes.set(name.name, evaluateJSXValue(value, strictCode, env, realm));
|
|
break;
|
|
case "JSXSpreadAttribute":
|
|
var spreadValue = _singletons.Environment.GetValue(realm, env.evaluate(astAttribute.argument, strictCode));
|
|
|
|
if (spreadValue instanceof _index.ObjectValue) {
|
|
var _iteratorNormalCompletion3 = true;
|
|
var _didIteratorError3 = false;
|
|
var _iteratorError3 = undefined;
|
|
|
|
try {
|
|
for (var _iterator3 = spreadValue.properties[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
|
|
var _ref3 = _step3.value;
|
|
|
|
var _ref4 = _slicedToArray(_ref3, 2);
|
|
|
|
var _key = _ref4[0];
|
|
var spreadProp = _ref4[1];
|
|
|
|
if (spreadProp !== undefined && spreadProp.descriptor !== undefined) {
|
|
var spreadPropValue = spreadProp.descriptor.value;
|
|
|
|
if (spreadPropValue instanceof _index.Value) {
|
|
if (_key === "children") {
|
|
children = spreadPropValue;
|
|
} else {
|
|
attributes.set(_key, spreadPropValue);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError3 = true;
|
|
_iteratorError3 = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion3 && _iterator3.return) {
|
|
_iterator3.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError3) {
|
|
throw _iteratorError3;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
throw new _errors.FatalError("ObjectValues are the only supported value for JSX Spread Attributes");
|
|
}
|
|
break;
|
|
default:
|
|
(0, _invariant2.default)(false, "Unknown JSX attribute type:: " + astAttribute.type);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError2 = true;
|
|
_iteratorError2 = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
|
_iterator2.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError2) {
|
|
throw _iteratorError2;
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
attributes: attributes,
|
|
children: children
|
|
};
|
|
}
|
|
|
|
function createReactProps(realm, type, attributes, children, env) {
|
|
var obj = _singletons.Create.ObjectCreate(realm, realm.intrinsics.ObjectPrototype);
|
|
var _iteratorNormalCompletion4 = true;
|
|
var _didIteratorError4 = false;
|
|
var _iteratorError4 = undefined;
|
|
|
|
try {
|
|
for (var _iterator4 = attributes[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
|
|
var _ref5 = _step4.value;
|
|
|
|
var _ref6 = _slicedToArray(_ref5, 2);
|
|
|
|
var key = _ref6[0];
|
|
var value = _ref6[1];
|
|
|
|
if (typeof key === "string") {
|
|
if (RESERVED_PROPS.hasOwnProperty(key)) {
|
|
continue;
|
|
}
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, obj, key, value);
|
|
}
|
|
}
|
|
} catch (err) {
|
|
_didIteratorError4 = true;
|
|
_iteratorError4 = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion4 && _iterator4.return) {
|
|
_iterator4.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError4) {
|
|
throw _iteratorError4;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (children !== null) {
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, obj, "children", children);
|
|
}
|
|
return obj;
|
|
}
|
|
|
|
function createReactElement(realm, type, key, ref, props) {
|
|
var obj = _singletons.Create.ObjectCreate(realm, realm.intrinsics.ObjectPrototype);
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, obj, "$$typeof", (0, _utils.getReactSymbol)("react.element", realm));
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, obj, "type", type);
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, obj, "key", key);
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, obj, "ref", ref);
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, obj, "props", props);
|
|
_singletons.Create.CreateDataPropertyOrThrow(realm, obj, "_owner", realm.intrinsics.null);
|
|
return obj;
|
|
}
|
|
//# sourceMappingURL=JSXElement.js.map
|