341 lines
18 KiB
JavaScript
341 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.ClassDefinitionEvaluation = ClassDefinitionEvaluation;
|
||
|
||
exports.default = function (ast, strictCode, env, realm) {
|
||
// 1. Let status be the result of BindingClassDeclarationEvaluation of this ClassDeclaration.
|
||
BindingClassDeclarationEvaluation(realm, ast, strictCode, env);
|
||
|
||
// 2. ReturnIfAbrupt(status).
|
||
|
||
// 3. Return NormalCompletion(empty).
|
||
return realm.intrinsics.empty;
|
||
};
|
||
|
||
var _index = require("../values/index.js");
|
||
|
||
var _errors = require("../errors.js");
|
||
|
||
var _parse = require("../utils/parse.js");
|
||
|
||
var _parse2 = _interopRequireDefault(_parse);
|
||
|
||
var _index2 = require("../methods/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 }; }
|
||
|
||
function EvaluateClassHeritage(realm, ClassHeritage, strictCode) {
|
||
var ref = realm.getRunningContext().lexicalEnvironment.evaluate(ClassHeritage, strictCode);
|
||
var val = _singletons.Environment.GetValue(realm, ref);
|
||
if (val instanceof _index.AbstractValue) {
|
||
var error = new _errors.CompilerDiagnostic("unknown super class", ClassHeritage.loc, "PP0009", "RecoverableError");
|
||
if (realm.handleError(error) === "Fail") throw new _errors.FatalError();
|
||
}
|
||
if (!(val instanceof _index.ObjectValue)) {
|
||
return null;
|
||
}
|
||
return val;
|
||
}
|
||
|
||
// ECMA262 14.5.14
|
||
function ClassDefinitionEvaluation(realm, ast, className, strictCode, env) {
|
||
// 1. Let lex be the LexicalEnvironment of the running execution context.
|
||
var lex = env;
|
||
|
||
// 2. Let classScope be NewDeclarativeEnvironment(lex).
|
||
var classScope = _singletons.Environment.NewDeclarativeEnvironment(realm, lex);
|
||
var F = void 0;
|
||
|
||
try {
|
||
// 3. Let classScopeEnvRec be classScope’s EnvironmentRecord.
|
||
var classScopeEnvRec = classScope.environmentRecord;
|
||
|
||
// 4. If className is not undefined, then
|
||
if (className !== undefined) {
|
||
// a. Perform classScopeEnvRec.CreateImmutableBinding(className, true).
|
||
classScopeEnvRec.CreateImmutableBinding(className, true);
|
||
}
|
||
|
||
var protoParent = void 0;
|
||
var constructorParent = void 0;
|
||
// 5. If ClassHeritage opt is not present, then
|
||
var ClassHeritage = ast.superClass;
|
||
if (!ClassHeritage) {
|
||
// a. Let protoParent be the intrinsic object %ObjectPrototype%.
|
||
protoParent = realm.intrinsics.ObjectPrototype;
|
||
|
||
// b. Let constructorParent be the intrinsic object %FunctionPrototype%.
|
||
constructorParent = realm.intrinsics.FunctionPrototype;
|
||
} else {
|
||
// 6. Else
|
||
// a. Set the running execution context’s LexicalEnvironment to classScope.
|
||
realm.getRunningContext().lexicalEnvironment = classScope;
|
||
var superclass = null;
|
||
try {
|
||
// b. Let superclass be the result of evaluating ClassHeritage.
|
||
superclass = EvaluateClassHeritage(realm, ClassHeritage, strictCode);
|
||
} finally {
|
||
// c. Set the running execution context’s LexicalEnvironment to lex.
|
||
realm.getRunningContext().lexicalEnvironment = lex;
|
||
}
|
||
|
||
// d. ReturnIfAbrupt(superclass).
|
||
|
||
// e. If superclass is null, then
|
||
if (superclass === null) {
|
||
// i. Let protoParent be null.
|
||
protoParent = realm.intrinsics.null;
|
||
|
||
// ii. Let constructorParent be the intrinsic object %FunctionPrototype%.
|
||
constructorParent = realm.intrinsics.FunctionPrototype;
|
||
} else if (!(0, _index2.IsConstructor)(realm, superclass)) {
|
||
// f. Else if IsConstructor(superclass) is false, throw a TypeError exception.
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "superclass must be a constructor");
|
||
} else {
|
||
// g. Else
|
||
// i. If superclass has a [[FunctionKind]] internal slot whose value is "generator", throw a TypeError exception.
|
||
if (superclass instanceof _index.ECMAScriptFunctionValue && superclass.$FunctionKind === "generator") {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "superclass cannot be a generator");
|
||
}
|
||
|
||
// ii. Let protoParent be Get(superclass, "prototype").
|
||
protoParent = (0, _index2.Get)(realm, superclass, "prototype");
|
||
|
||
// iii. ReturnIfAbrupt(protoParent).
|
||
|
||
// iv. If Type(protoParent) is neither Object nor Null, throw a TypeError exception.
|
||
if (!(protoParent instanceof _index.ObjectValue || protoParent instanceof _index.NullValue)) {
|
||
if (protoParent instanceof _index.AbstractValue) {
|
||
var error = new _errors.CompilerDiagnostic("unknown super class prototype", ClassHeritage.loc, "PP0010", "RecoverableError");
|
||
if (realm.handleError(error) === "Fail") throw new _errors.FatalError();
|
||
protoParent = realm.intrinsics.ObjectPrototype;
|
||
} else {
|
||
throw realm.createErrorThrowCompletion(realm.intrinsics.TypeError, "protoParent must be an instance of Object or Null");
|
||
}
|
||
}
|
||
|
||
// v. Let constructorParent be superclass.
|
||
constructorParent = superclass;
|
||
}
|
||
}
|
||
|
||
// 7. Let proto be ObjectCreate(protoParent).
|
||
var proto = _singletons.Create.ObjectCreate(realm, protoParent);
|
||
|
||
// react. Check the Flow class paramater annotations, stored in "superTypeParameters"
|
||
if (realm.react.enabled && realm.react.flowRequired && ast.superTypeParameters) {
|
||
proto.$SuperTypeParameters = ast.superTypeParameters;
|
||
}
|
||
var _constructor = void 0;
|
||
var ClassBody = [];
|
||
var _iteratorNormalCompletion = true;
|
||
var _didIteratorError = false;
|
||
var _iteratorError = undefined;
|
||
|
||
try {
|
||
for (var _iterator = ast.body.body[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||
var elem = _step.value;
|
||
|
||
if (elem.type === "ClassMethod") {
|
||
ClassBody.push(elem);
|
||
}
|
||
}
|
||
// 8. If ClassBody opt is not present, let constructor be empty.
|
||
} catch (err) {
|
||
_didIteratorError = true;
|
||
_iteratorError = err;
|
||
} finally {
|
||
try {
|
||
if (!_iteratorNormalCompletion && _iterator.return) {
|
||
_iterator.return();
|
||
}
|
||
} finally {
|
||
if (_didIteratorError) {
|
||
throw _iteratorError;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (ClassBody.length === 0) {
|
||
_constructor = realm.intrinsics.empty;
|
||
} else {
|
||
// 9. Else, let constructor be ConstructorMethod of ClassBody.
|
||
_constructor = (0, _index2.ConstructorMethod)(realm, ClassBody);
|
||
}
|
||
|
||
// 10. If constructor is empty, then,
|
||
if (_constructor instanceof _index.EmptyValue) {
|
||
var constructorFile = void 0;
|
||
// a. If ClassHeritage opt is present, then
|
||
if (ast.superClass) {
|
||
// i. Let constructor be the result of parsing the source text
|
||
// constructor(... args){ super (...args);}
|
||
// using the syntactic grammar with the goal symbol MethodDefinition.
|
||
constructorFile = (0, _parse2.default)(realm, "class NeedClassForParsing { constructor(... args){ super (...args);} }", "");
|
||
} else {
|
||
// b. Else,
|
||
// i. Let constructor be the result of parsing the source text
|
||
// constructor( ){ }
|
||
// using the syntactic grammar with the goal symbol MethodDefinition.
|
||
constructorFile = (0, _parse2.default)(realm, "class NeedClassForParsing { constructor( ){ } }", "");
|
||
}
|
||
|
||
var _constructorFile = constructorFile,
|
||
_constructorFile$prog = _slicedToArray(_constructorFile.program.body, 1),
|
||
classDeclaration = _constructorFile$prog[0];
|
||
|
||
(0, _invariant2.default)(classDeclaration.type === "ClassDeclaration");
|
||
var _ref = classDeclaration,
|
||
body = _ref.body;
|
||
|
||
(0, _invariant2.default)(body.body[0].type === "ClassMethod");
|
||
_constructor = body.body[0];
|
||
}
|
||
|
||
// 11. Set the running execution context’s LexicalEnvironment to classScope.
|
||
realm.getRunningContext().lexicalEnvironment = classScope;
|
||
|
||
try {
|
||
// 12. Let constructorInfo be the result of performing DefineMethod for constructor with arguments proto and constructorParent as the optional functionPrototype argument.
|
||
var constructorInfo = _singletons.Functions.DefineMethod(realm, _constructor, proto, env, strictCode, constructorParent);
|
||
|
||
// 13. Assert: constructorInfo is not an abrupt completion.
|
||
|
||
// 14. Let F be constructorInfo.[[closure]]
|
||
F = constructorInfo.$Closure;
|
||
|
||
// 15. If ClassHeritage opt is present, set F’s [[ConstructorKind]] internal slot to "derived".
|
||
if (ast.superClass) {
|
||
F.$ConstructorKind = "derived";
|
||
}
|
||
|
||
// 16. Perform MakeConstructor(F, false, proto).
|
||
(0, _index2.MakeConstructor)(realm, F, false, proto);
|
||
|
||
// 17. Perform MakeClassConstructor(F).
|
||
(0, _index2.MakeClassConstructor)(realm, F);
|
||
|
||
// 18. Perform CreateMethodProperty(proto, "constructor", F).
|
||
_singletons.Create.CreateMethodProperty(realm, proto, "constructor", F);
|
||
|
||
var methods = void 0;
|
||
// 19. If ClassBody opt is not present, let methods be a new empty List.
|
||
if (ClassBody.length === 0) {
|
||
methods = [];
|
||
} else {
|
||
// 20. Else, let methods be NonConstructorMethodDefinitions of ClassBody.
|
||
methods = (0, _index2.NonConstructorMethodDefinitions)(realm, ClassBody);
|
||
}
|
||
|
||
// 21. For each ClassElement m in order from methods
|
||
var _iteratorNormalCompletion2 = true;
|
||
var _didIteratorError2 = false;
|
||
var _iteratorError2 = undefined;
|
||
|
||
try {
|
||
for (var _iterator2 = methods[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
||
var m = _step2.value;
|
||
|
||
// a. If IsStatic of m is false, then
|
||
if (!(0, _index2.IsStatic)(m)) {
|
||
// Let status be the result of performing PropertyDefinitionEvaluation for m with arguments proto and false.
|
||
_singletons.Properties.PropertyDefinitionEvaluation(realm, m, proto, env, strictCode, false);
|
||
} else {
|
||
// Else,
|
||
// Let status be the result of performing PropertyDefinitionEvaluation for m with arguments F and false.
|
||
_singletons.Properties.PropertyDefinitionEvaluation(realm, m, F, env, strictCode, false);
|
||
}
|
||
// c. If status is an abrupt completion, then
|
||
// i. Set the running execution context's LexicalEnvironment to lex.
|
||
// ii. Return Completion(status).
|
||
}
|
||
} catch (err) {
|
||
_didIteratorError2 = true;
|
||
_iteratorError2 = err;
|
||
} finally {
|
||
try {
|
||
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
||
_iterator2.return();
|
||
}
|
||
} finally {
|
||
if (_didIteratorError2) {
|
||
throw _iteratorError2;
|
||
}
|
||
}
|
||
}
|
||
} finally {
|
||
// 22. Set the running execution context’s LexicalEnvironment to lex.
|
||
realm.getRunningContext().lexicalEnvironment = lex;
|
||
}
|
||
|
||
// 23. If className is not undefined, then
|
||
if (className !== undefined) {
|
||
// Perform classScopeEnvRec.InitializeBinding(className, F).
|
||
classScopeEnvRec.InitializeBinding(className, F);
|
||
}
|
||
} finally {
|
||
realm.onDestroyScope(classScope);
|
||
}
|
||
// Return F.
|
||
return F;
|
||
}
|
||
|
||
// ECMA2 14.5.15
|
||
function BindingClassDeclarationEvaluation(realm, ast, strictCode, env) {
|
||
// ClassDeclaration : class BindingIdentifier ClassTail
|
||
if (ast.id) {
|
||
// 1. Let className be StringValue of BindingIdentifier.
|
||
var className = ast.id.name;
|
||
|
||
// 2. Let value be the result of ClassDefinitionEvaluation of ClassTail with argument className.
|
||
var value = ClassDefinitionEvaluation(realm, ast, className, strictCode, env);
|
||
|
||
// 3. ReturnIfAbrupt(value).
|
||
|
||
// 4. Let hasNameProperty be HasOwnProperty(value, "name").
|
||
var hasNameProperty = (0, _index2.HasOwnProperty)(realm, value, "name");
|
||
|
||
// 5. ReturnIfAbrupt(hasNameProperty).
|
||
|
||
// 6. If hasNameProperty is false, then perform SetFunctionName(value, className).
|
||
if (hasNameProperty === false) {
|
||
_singletons.Functions.SetFunctionName(realm, value, className);
|
||
}
|
||
|
||
// 7. Let env be the running execution context’s LexicalEnvironment.
|
||
|
||
// 8. Let status be InitializeBoundName(className, value, env).
|
||
_singletons.Environment.InitializeBoundName(realm, className, value, env);
|
||
|
||
// 9. ReturnIfAbrupt(status).
|
||
|
||
// 10. Return value.
|
||
return value;
|
||
} else {
|
||
// ClassDeclaration : class ClassTail
|
||
// 1. Return the result of ClassDefinitionEvaluation of ClassTail with argument undefined.
|
||
return ClassDefinitionEvaluation(realm, ast, undefined, strictCode, env);
|
||
}
|
||
}
|
||
|
||
// ECMA262 14.5.16
|
||
//# sourceMappingURL=ClassDeclaration.js.map
|