532 lines
24 KiB
JavaScript
532 lines
24 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.GetFunctionRealm = GetFunctionRealm;
|
|
exports.OrdinaryGet = OrdinaryGet;
|
|
exports.GetGlobalObject = GetGlobalObject;
|
|
exports.GetSubstitution = GetSubstitution;
|
|
exports.GetMethod = GetMethod;
|
|
exports.GetPrototypeFromConstructor = GetPrototypeFromConstructor;
|
|
exports.Get = Get;
|
|
exports.GetV = GetV;
|
|
exports.GetThisValue = GetThisValue;
|
|
exports.GetNewTarget = GetNewTarget;
|
|
exports.GetTemplateObject = GetTemplateObject;
|
|
|
|
var _completions = require("../completions.js");
|
|
|
|
var _realm = require("../realm.js");
|
|
|
|
var _index = require("../values/index.js");
|
|
|
|
var _environment = require("../environment.js");
|
|
|
|
var _errors = require("../errors.js");
|
|
|
|
var _integrity = require("./integrity.js");
|
|
|
|
var _index2 = require("./index.js");
|
|
|
|
var _singletons = require("../singletons.js");
|
|
|
|
var _invariant = require("../invariant.js");
|
|
|
|
var _invariant2 = _interopRequireDefault(_invariant);
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
// ECMA262 7.3.22
|
|
function GetFunctionRealm(realm, obj) {
|
|
// 1. Assert: obj is a callable object.
|
|
(0, _invariant2.default)((0, _index2.IsCallable)(realm, obj), "expected callable object");
|
|
|
|
// 2. If obj has a [[Realm]] internal slot, then
|
|
if (obj.$Realm) {
|
|
// a. Return obj's [[Realm]] internal slot.
|
|
return obj.$Realm;
|
|
}
|
|
|
|
// 3. If obj is a Bound Function exotic object, then
|
|
if (obj instanceof _index.BoundFunctionValue) {
|
|
// a. Let target be obj's [[BoundTargetFunction]] internal slot.
|
|
var target = obj.$BoundTargetFunction;
|
|
|
|
// b. Return ? GetFunctionRealm(target).
|
|
return GetFunctionRealm(realm, target);
|
|
}
|
|
|
|
// 4. If obj is a Proxy exotic object, then
|
|
if (obj instanceof _index.ProxyValue) {
|
|
// a. If the value of the [[ProxyHandler]] internal slot of obj is null, throw a TypeError exception.
|
|
if (obj.$ProxyHandler instanceof _index.NullValue) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "proxy handler is null");
|
|
}
|
|
(0, _invariant2.default)(obj.$ProxyTarget instanceof _index.ObjectValue);
|
|
|
|
// b. Let proxyTarget be the value of obj's [[ProxyTarget]] internal slot.
|
|
var proxyTarget = obj.$ProxyTarget;
|
|
|
|
// c. Return ? GetFunctionRealm(proxyTarget).
|
|
return GetFunctionRealm(realm, proxyTarget);
|
|
}
|
|
|
|
// 5. Return the current Realm Record.
|
|
return realm;
|
|
}
|
|
|
|
// ECMA262 9.1.8.1
|
|
function OrdinaryGet(realm, O, P, Receiver, dataOnly) {
|
|
// 1. Assert: IsPropertyKey(P) is true.
|
|
(0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "expected property key");
|
|
|
|
// 2. Let desc be ? O.[[GetOwnProperty]](P).
|
|
var desc = O.$GetOwnProperty(P);
|
|
if (desc !== undefined && desc.joinCondition !== undefined) {
|
|
// joined descriptors need special treatment
|
|
var joinCondition = desc.joinCondition;
|
|
if (joinCondition !== undefined) {
|
|
var descriptor2 = desc.descriptor2;
|
|
desc = desc.descriptor1;
|
|
|
|
var _Path$withCondition = _singletons.Path.withCondition(joinCondition, function () {
|
|
return desc !== undefined ? realm.evaluateForEffects(function () {
|
|
return OrdinaryGetHelper();
|
|
}) : (0, _realm.construct_empty_effects)(realm);
|
|
}),
|
|
_Path$withCondition2 = _slicedToArray(_Path$withCondition, 5),
|
|
compl1 = _Path$withCondition2[0],
|
|
gen1 = _Path$withCondition2[1],
|
|
bindings1 = _Path$withCondition2[2],
|
|
properties1 = _Path$withCondition2[3],
|
|
createdObj1 = _Path$withCondition2[4];
|
|
|
|
desc = descriptor2;
|
|
|
|
var _Path$withInverseCond = _singletons.Path.withInverseCondition(joinCondition, function () {
|
|
return desc !== undefined ? realm.evaluateForEffects(function () {
|
|
return OrdinaryGetHelper();
|
|
}) : (0, _realm.construct_empty_effects)(realm);
|
|
}),
|
|
_Path$withInverseCond2 = _slicedToArray(_Path$withInverseCond, 5),
|
|
compl2 = _Path$withInverseCond2[0],
|
|
gen2 = _Path$withInverseCond2[1],
|
|
bindings2 = _Path$withInverseCond2[2],
|
|
properties2 = _Path$withInverseCond2[3],
|
|
createdObj2 = _Path$withInverseCond2[4];
|
|
|
|
// Join the effects, creating an abstract view of what happened, regardless
|
|
// of the actual value of ownDesc.joinCondition.
|
|
|
|
|
|
var joinedEffects = _singletons.Join.joinEffects(realm, joinCondition, [compl1, gen1, bindings1, properties1, createdObj1], [compl2, gen2, bindings2, properties2, createdObj2]);
|
|
var completion = joinedEffects[0];
|
|
if (completion instanceof _completions.PossiblyNormalCompletion) {
|
|
// in this case one of the branches may complete abruptly, which means that
|
|
// not all control flow branches join into one flow at this point.
|
|
// Consequently we have to continue tracking changes until the point where
|
|
// all the branches come together into one.
|
|
completion = realm.composeWithSavedCompletion(completion);
|
|
}
|
|
// Note that the effects of (non joining) abrupt branches are not included
|
|
// in joinedEffects, but are tracked separately inside completion.
|
|
realm.applyEffects(joinedEffects);
|
|
|
|
// return or throw completion
|
|
if (completion instanceof _completions.AbruptCompletion) throw completion;
|
|
(0, _invariant2.default)(completion instanceof _index.Value);
|
|
return completion;
|
|
}
|
|
}
|
|
|
|
return OrdinaryGetHelper();
|
|
|
|
function OrdinaryGetHelper() {
|
|
var descValue = !desc ? realm.intrinsics.undefined : desc.value === undefined ? realm.intrinsics.undefined : desc.value;
|
|
(0, _invariant2.default)(descValue instanceof _index.Value);
|
|
|
|
// 3. If desc is undefined, then
|
|
if (!desc || descValue.mightHaveBeenDeleted()) {
|
|
// a. Let parent be ? O.[[GetPrototypeOf]]().
|
|
var parent = O.$GetPrototypeOf();
|
|
|
|
// b. If parent is null, return undefined.
|
|
if (parent instanceof _index.NullValue) {
|
|
// Return the property value since it is now known to be the right value
|
|
// even in the case when it is empty.
|
|
return descValue;
|
|
}
|
|
|
|
// c. Return ? parent.[[Get]](P, Receiver).
|
|
if (descValue.mightHaveBeenDeleted() && descValue instanceof _index.AbstractValue) {
|
|
// We don't know for sure that O.P does not exist.
|
|
var parentVal = OrdinaryGet(realm, parent, P, descValue, true);
|
|
if (parentVal instanceof _index.UndefinedValue)
|
|
// even O.P returns undefined it is still the right value.
|
|
return descValue;
|
|
// Join with parent value with descValue because the actual value will be
|
|
// descValue unless it is empty.
|
|
// Only get the parent value if it does not involve a getter call.
|
|
// Use a property get for the joined value since it does the check for empty.
|
|
var cond = _index.AbstractValue.createFromBinaryOp(realm, "!==", descValue, realm.intrinsics.empty);
|
|
return _singletons.Join.joinValuesAsConditional(realm, cond, descValue, parentVal);
|
|
}
|
|
(0, _invariant2.default)(!desc || descValue instanceof _index.EmptyValue);
|
|
return parent.$Get(P, Receiver);
|
|
}
|
|
|
|
// 4. If IsDataDescriptor(desc) is true, return desc.[[Value]].
|
|
if ((0, _index2.IsDataDescriptor)(realm, desc)) return descValue;
|
|
if (dataOnly) {
|
|
(0, _invariant2.default)(descValue instanceof _index.AbstractValue);
|
|
_index.AbstractValue.reportIntrospectionError(descValue);
|
|
throw new _errors.FatalError();
|
|
}
|
|
|
|
// 5. Assert: IsAccessorDescriptor(desc) is true.
|
|
(0, _invariant2.default)((0, _index2.IsAccessorDescriptor)(realm, desc), "expected accessor descriptor");
|
|
|
|
// 6. Let getter be desc.[[Get]].
|
|
var getter = desc.get;
|
|
|
|
// 7. If getter is undefined, return undefined.
|
|
if (!getter || getter instanceof _index.UndefinedValue) return realm.intrinsics.undefined;
|
|
|
|
// 8. Return ? Call(getter, Receiver).
|
|
return (0, _index2.Call)(realm, getter, Receiver);
|
|
}
|
|
}
|
|
|
|
// ECMA262 8.3.6
|
|
function GetGlobalObject(realm) {
|
|
// 1. Let ctx be the running execution context.
|
|
var ctx = realm.getRunningContext();
|
|
|
|
// 2. Let currentRealm be ctx's Realm.
|
|
var currentRealm = ctx.realm;
|
|
|
|
// 3. Return currentRealm.[[GlobalObject]].
|
|
return currentRealm.$GlobalObject;
|
|
}
|
|
|
|
// ECMA262 21.1.3.14.1
|
|
function GetSubstitution(realm, matched, str, position, captures, replacement) {
|
|
// 1. Assert: Type(matched) is String.
|
|
(0, _invariant2.default)(typeof matched === "string", "expected matched to be a stirng");
|
|
|
|
// 2. Let matchLength be the number of code units in matched.
|
|
var matchLength = matched.length;
|
|
|
|
// 3. Assert: Type(str) is String.
|
|
(0, _invariant2.default)(typeof str === "string", "expected matched to be a stirng");
|
|
|
|
// 4. Let stringLength be the number of code units in str.
|
|
var stringLength = str.length;
|
|
|
|
// 5. Assert: position is a nonnegative integer.
|
|
(0, _invariant2.default)(position >= 0, "expected position to be a nonegative integer");
|
|
|
|
// 6. Assert: position ≤ stringLength.
|
|
(0, _invariant2.default)(position <= stringLength, "expected position to be less than string length");
|
|
|
|
// 7. Assert: captures is a possibly empty List of Strings.
|
|
(0, _invariant2.default)(Array.isArray(captures), "expected captures to be an array");
|
|
|
|
// 8. Assert: Type(replacement) is String.
|
|
(0, _invariant2.default)(typeof replacement === "string", "expected replacement to be a stirng");
|
|
|
|
// 9. Let tailPos be position + matchLength.
|
|
var tailPos = position + matchLength;
|
|
|
|
// 10. Let m be the number of elements in captures.
|
|
var m = captures.length;
|
|
|
|
// 11. Let result be a String value derived from replacement by copying code unit elements
|
|
// from replacement to result while performing replacements as specified in Table 46.
|
|
// These $ replacements are done left-to-right, and, once such a replacement is performed,
|
|
// the new replacement text is not subject to further replacements.
|
|
var result = "";
|
|
for (var i = 0; i < replacement.length; ++i) {
|
|
var ch = replacement.charAt(i);
|
|
if (ch !== "$" || i + 1 >= replacement.length) {
|
|
result += ch;
|
|
continue;
|
|
}
|
|
var peek = replacement.charAt(i + 1);
|
|
if (peek === "&") {
|
|
result += matched;
|
|
} else if (peek === "$") {
|
|
result += "$";
|
|
} else if (peek === "`") {
|
|
result += str.substr(0, position);
|
|
} else if (peek === "'") {
|
|
result += str.substr(tailPos);
|
|
} else if (peek >= "0" && peek <= "9") {
|
|
var idx = peek.charCodeAt(0) - "0".charCodeAt(0);
|
|
if (i + 2 < replacement.length) {
|
|
var peek2 = replacement.charAt(i + 2);
|
|
if (peek2 >= "0" && peek2 <= "9") {
|
|
var newIdx = idx * 10 + (peek2.charCodeAt(0) - "0".charCodeAt(0));
|
|
if (newIdx <= m) {
|
|
idx = newIdx;
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
if (idx > 0 && idx <= m) {
|
|
result += captures[idx - 1] || "";
|
|
} else {
|
|
result += "$" + idx;
|
|
}
|
|
} else {
|
|
result += "$" + peek;
|
|
}
|
|
i += 1;
|
|
}
|
|
|
|
// 12. Return result.
|
|
return result;
|
|
}
|
|
|
|
// ECMA262 7.3.9
|
|
function GetMethod(realm, V, P) {
|
|
// 1. Assert: IsPropertyKey(P) is true.
|
|
(0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "expected property key");
|
|
|
|
// 2. Let func be ? GetV(V, P).
|
|
var func = GetV(realm, V, P);
|
|
|
|
// 3. If func is either undefined or null, return undefined.
|
|
if ((0, _index2.HasSomeCompatibleType)(func, _index.NullValue, _index.UndefinedValue)) {
|
|
return realm.intrinsics.undefined;
|
|
}
|
|
|
|
// 4. If IsCallable(func) is false, throw a TypeError exception.
|
|
if (!(0, _index2.IsCallable)(realm, func)) {
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "not callable");
|
|
}
|
|
|
|
// 5. Return func.
|
|
return func;
|
|
}
|
|
|
|
// ECMA262 9.1.14
|
|
function GetPrototypeFromConstructor(realm, constructor, intrinsicDefaultProto) {
|
|
// 1. Assert: intrinsicDefaultProto is a String value that is this specification's name of an intrinsic
|
|
// object. The corresponding object must be an intrinsic that is intended to be used as the [[Prototype]]
|
|
// value of an object.
|
|
(0, _invariant2.default)(realm.intrinsics[intrinsicDefaultProto], "not a valid proto ref");
|
|
|
|
// 2. Assert: IsCallable(constructor) is true.
|
|
(0, _invariant2.default)((0, _index2.IsCallable)(realm, constructor) === true, "expected constructor to be callable");
|
|
|
|
// 3. Let proto be ? Get(constructor, "prototype").
|
|
var proto = Get(realm, constructor, new _index.StringValue(realm, "prototype"));
|
|
|
|
// 4. If Type(proto) is not Object, then
|
|
if (!(proto instanceof _index.ObjectValue)) {
|
|
// a. Let realm be ? GetFunctionRealm(constructor).
|
|
realm = GetFunctionRealm(realm, constructor);
|
|
|
|
// b. Let proto be realm's intrinsic object named intrinsicDefaultProto.
|
|
proto = realm.intrinsics[intrinsicDefaultProto];
|
|
}
|
|
|
|
// 5. Return proto.
|
|
return proto;
|
|
}
|
|
|
|
// ECMA262 7.3.1
|
|
function Get(realm, O, P) {
|
|
// 1. Assert: Type(O) is Object.
|
|
(0, _invariant2.default)(O instanceof _index.ObjectValue || O instanceof _index.AbstractObjectValue, "Not an object value");
|
|
|
|
// 2. Assert: IsPropertyKey(P) is true.
|
|
(0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "Not a valid property key");
|
|
|
|
// 3. Return ? O.[[Get]](P, O).
|
|
return O.$Get(P, O);
|
|
}
|
|
|
|
// ECMA262 7.3.2
|
|
function GetV(realm, V, P) {
|
|
// 1. Assert: IsPropertyKey(P) is true.
|
|
(0, _invariant2.default)((0, _index2.IsPropertyKey)(realm, P), "Not a valid property key");
|
|
|
|
// 2. Let O be ? ToObject(V).
|
|
var O = _singletons.To.ToObjectPartial(realm, V);
|
|
|
|
// 3. Return ? O.[[Get]](P, V).
|
|
return O.$Get(P, V);
|
|
}
|
|
|
|
// ECMA262 6.2.3.3
|
|
function GetThisValue(realm, V) {
|
|
// 1. Assert: IsPropertyReference(V) is true.
|
|
(0, _invariant2.default)(_singletons.Environment.IsPropertyReference(realm, V), "expected property reference");
|
|
|
|
// 2. If IsSuperReference(V) is true, then
|
|
if (_singletons.Environment.IsSuperReference(realm, V)) {
|
|
(0, _invariant2.default)(V.thisValue !== undefined);
|
|
// a. Return the value of the thisValue component of the reference V.
|
|
return V.thisValue;
|
|
}
|
|
|
|
// 3. Return GetBase(V).
|
|
var result = _singletons.Environment.GetBase(realm, V);
|
|
(0, _invariant2.default)(result instanceof _index.Value);
|
|
return result;
|
|
}
|
|
|
|
// ECMA262 8.3.5
|
|
function GetNewTarget(realm) {
|
|
// 1. Let envRec be GetThisEnvironment( ).
|
|
var envRec = _singletons.Environment.GetThisEnvironment(realm);
|
|
|
|
// 2. Assert: envRec has a [[NewTarget]] field.
|
|
if (!("$NewTarget" in envRec)) {
|
|
// In the spec we should not get here because earlier static checks are supposed to prevent it.
|
|
// However, we do not have an appropriate place to do this check earlier.
|
|
throw realm.createErrorThrowCompletion(realm.intrinsics.SyntaxError, "new.target not allowed here");
|
|
}
|
|
|
|
// 3. Return envRec.[[NewTarget]].
|
|
return envRec.$NewTarget || realm.intrinsics.undefined;
|
|
}
|
|
|
|
function GetTemplateObject(realm, templateLiteral) {
|
|
// 1. Let rawStrings be TemplateStrings of templateLiteral with argument true.
|
|
var rawStrings = templateLiteral.quasis.map(function (quasi) {
|
|
return quasi.value.raw;
|
|
});
|
|
|
|
// 2. Let realm be the current Realm Record.
|
|
realm;
|
|
|
|
// 3. Let templateRegistry be realm.[[TemplateMap]].
|
|
var templateRegistry = realm.$TemplateMap;
|
|
|
|
// 4. For each element e of templateRegistry, do
|
|
var _iteratorNormalCompletion = true;
|
|
var _didIteratorError = false;
|
|
var _iteratorError = undefined;
|
|
|
|
try {
|
|
for (var _iterator = templateRegistry[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
|
var e = _step.value;
|
|
|
|
var same = void 0;
|
|
if (e.$Strings.length === rawStrings.length) {
|
|
same = true;
|
|
for (var i = 0; i < rawStrings.length; ++i) {
|
|
if (e.$Strings[i] !== rawStrings[i]) {
|
|
same = false;
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
same = false;
|
|
}
|
|
|
|
// a. If e.[[Strings]] and rawStrings contain the same values in the same order, then
|
|
if (same) {
|
|
// i. Return e.[[Array]].
|
|
return e.$Array;
|
|
}
|
|
}
|
|
|
|
// 5. Let cookedStrings be TemplateStrings of templateLiteral with argument false.
|
|
} catch (err) {
|
|
_didIteratorError = true;
|
|
_iteratorError = err;
|
|
} finally {
|
|
try {
|
|
if (!_iteratorNormalCompletion && _iterator.return) {
|
|
_iterator.return();
|
|
}
|
|
} finally {
|
|
if (_didIteratorError) {
|
|
throw _iteratorError;
|
|
}
|
|
}
|
|
}
|
|
|
|
var cookedStrings = templateLiteral.quasis.map(function (quasi) {
|
|
return quasi.value.cooked;
|
|
});
|
|
|
|
// 6. Let count be the number of elements in the List cookedStrings.
|
|
var count = cookedStrings.length;
|
|
|
|
// 7. Let template be ArrayCreate(count).
|
|
var template = _singletons.Create.ArrayCreate(realm, count);
|
|
|
|
// 8. Let rawObj be ArrayCreate(count).
|
|
var rawObj = _singletons.Create.ArrayCreate(realm, count);
|
|
|
|
// 9. Let index be 0.
|
|
var index = 0;
|
|
|
|
// 10. Repeat while index < count
|
|
while (index < count) {
|
|
// a. Let prop be ! ToString(index).
|
|
var prop = _singletons.To.ToString(realm, new _index.NumberValue(realm, index));
|
|
|
|
// b. Let cookedValue be the String value cookedStrings[index].
|
|
var cookedValue = new _index.StringValue(realm, cookedStrings[index]);
|
|
|
|
// c. Call template.[[DefineOwnProperty]](prop, PropertyDescriptor{[[Value]]: cookedValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false}).
|
|
template.$DefineOwnProperty(prop, {
|
|
value: cookedValue,
|
|
writable: false,
|
|
enumerable: true,
|
|
configurable: false
|
|
});
|
|
|
|
// d. Let rawValue be the String value rawStrings[index].
|
|
var rawValue = new _index.StringValue(realm, rawStrings[index]);
|
|
|
|
// e. Call rawObj.[[DefineOwnProperty]](prop, PropertyDescriptor{[[Value]]: rawValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false}).
|
|
rawObj.$DefineOwnProperty(prop, {
|
|
value: rawValue,
|
|
writable: false,
|
|
enumerable: true,
|
|
configurable: false
|
|
});
|
|
|
|
// f. Let index be index+1.
|
|
index = index + 1;
|
|
}
|
|
|
|
// 11. Perform SetIntegrityLevel(rawObj, "frozen").
|
|
(0, _integrity.SetIntegrityLevel)(realm, rawObj, "frozen");
|
|
|
|
// 12. Call template.[[DefineOwnProperty]]("raw", PropertyDescriptor{[[Value]]: rawObj, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false}).
|
|
template.$DefineOwnProperty("raw", {
|
|
value: rawObj,
|
|
writable: false,
|
|
enumerable: false,
|
|
configurable: false
|
|
});
|
|
|
|
// 13. Perform SetIntegrityLevel(template, "frozen").
|
|
(0, _integrity.SetIntegrityLevel)(realm, template, "frozen");
|
|
|
|
// 14. Append the Record{[[Strings]]: rawStrings, [[Array]]: template} to templateRegistry.
|
|
templateRegistry.push({ $Strings: rawStrings, $Array: template });
|
|
|
|
// 15. Return template.
|
|
return template;
|
|
}
|
|
//# sourceMappingURL=get.js.map
|