From 161c9622fc2a4062f23a08bbb307854b3f1f746f Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 13 Sep 2026 12:15:18 +0000 Subject: [PATCH 1/2] [JSC] new.target in a class field initializer or a class static block does not make the code around the class a user of new.target A class field initializer and a class static block are functions of their own at run time (ClassFieldInitializerMode, ClassStaticBlockMode). They run as a method call, so new.target is undefined in them. parseClass() parses the source of both in place, with the scopes and the tree builder of the code around the class: parseAssignmentExpression(context) for a field initializer and parseBlockStatement(context, BlockType::StaticBlock) for a static block. That parse checks the syntax and finds the end. Each function is parsed again, on its own, when it is compiled. For new.target, parseMemberExpression() calls context.createNewTargetExpr(), which sets NewTargetFeature on the code that the tree builder builds. In the in-place parse that is the code around the class. It also calls setInnerArrowFunctionUsesNewTarget() on the current scope when the scope inherited isArrowFunction, which is true for a class scope in an arrow function. BytecodeGenerator emits emitLoadNewTargetFromArrowFunctionLexicalEnvironment() on entry to an arrow function, and to eval code, that needsNewTargetRegisterForThisScope(). It resolves @newTargetLocal with ThrowIfNotFound. So this throws "ReferenceError: Can't find private variable: PrivateSymbol.newTargetLocal" when the arrow function is called: (() => { class A { x = new.target; } })(); No function is around the arrow function, so nothing stored @newTargetLocal. The same happens for a static field, for a static block, for an async arrow function (the call throws, the promise does not reject), and for (0, eval)("class A { x = new.target }"). With a function around the arrow function, a field works by accident: the class scope passes the inner arrow function feature up to the function, and the function stores its new.target for the arrow function to load. A static block scope is a function boundary and does not pass the feature up, so this throws too: function f() { (() => { class A { static { new.target; } } })(); } Add Parser::isDirectlyInClassElementParsedInPlace(). It walks up from the current scope to the first function boundary. It returns true for a class scope with the new isParsingFieldInitializerInPlace flag, which parseClass() sets while it parses a field initializer, and for a static block scope that is not the outermost scope of the parser. When it returns true, parseMemberExpression() does not call setInnerArrowFunctionUsesNewTarget() and createNewTargetExpr() does not record NewTargetFeature. The parse of the class element as a function of its own is not in place, so it records the feature on that function as before. new.target in an arrow function in a class element is not changed either: the arrow function records the inner arrow function feature, and the function of the class element stores its (undefined) new.target for it. --- ...lass-field-initializer-and-static-block.js | 152 ++++++++++++++++++ Source/JavaScriptCore/parser/ASTBuilder.h | 7 +- Source/JavaScriptCore/parser/Parser.cpp | 11 +- Source/JavaScriptCore/parser/Parser.h | 23 +++ Source/JavaScriptCore/parser/SyntaxChecker.h | 2 +- 5 files changed, 190 insertions(+), 5 deletions(-) create mode 100644 JSTests/stress/new-target-in-class-field-initializer-and-static-block.js diff --git a/JSTests/stress/new-target-in-class-field-initializer-and-static-block.js b/JSTests/stress/new-target-in-class-field-initializer-and-static-block.js new file mode 100644 index 000000000000..9819a73ba4d0 --- /dev/null +++ b/JSTests/stress/new-target-in-class-field-initializer-and-static-block.js @@ -0,0 +1,152 @@ +// new.target in a class field initializer or in a class static block is the new.target of that class element. +// It is undefined. It must not make the code around the class a user of new.target. + +function shouldBe(actual, expected, message) { + if (actual !== expected) + throw new Error(message + ": expected " + String(expected) + " but got " + String(actual)); +} + +function shouldBeAsync(promise, expected, message) { + let result; + let error; + promise.then(value => { result = value; }, e => { error = e; }); + drainMicrotasks(); + if (error) + throw error; + shouldBe(result, expected, message); +} + +// The class is in an arrow function in global code. +{ + const instanceField = () => { class A { x = typeof new.target; } return new A().x; }; + const staticField = () => { class A { static x = typeof new.target; } return A.x; }; + const staticBlock = () => { let r; class A { static { r = typeof new.target; } } return r; }; + const privateField = () => { class A { #x = typeof new.target; get x() { return this.#x; } } return new A().x; }; + const computedField = () => { class A { ["x"] = typeof new.target; } return new A().x; }; + const classExpression = () => new (class { x = typeof new.target; })().x; + const derivedClass = () => { class B { } class A extends B { x = typeof new.target; } return new A().x; }; + const classWithConstructor = () => { class A { x = typeof new.target; constructor() { this.y = new.target; } } let a = new A(); return a.x + " " + (a.y === A); }; + const arrowInArrow = () => (() => { class A { x = typeof new.target; } return new A().x; })(); + const arrowInField = () => { class A { x = (() => typeof new.target)(); } return new A().x; }; + const arrowInStaticBlock = () => { let r; class A { static { r = (() => typeof new.target)(); } } return r; }; + const blockInStaticBlock = () => { let r; class A { static { if (true) { r = typeof new.target; } } } return r; }; + const keyOfClassInField = () => { class A { x = class { static [typeof new.target] = 1; }; } return Object.keys(new A().x)[0]; }; + const fieldOfClassInField = () => { class A { x = class { static y = typeof new.target; }; } return new A().x.y; }; + const fieldOfClassInStaticBlock = () => { let r; class A { static { class B { y = typeof new.target; } r = new B().y; } } return r; }; + const parameterOfArrowInField = () => { class A { x = ((y = typeof new.target) => y)(); } return new A().x; }; + const evalInField = () => { class A { x = eval("typeof new.target"); } return new A().x; }; + const evalInStaticBlock = () => { let r; class A { static { r = eval("typeof new.target"); } } return r; }; + + for (let i = 0; i < 100; ++i) { + shouldBe(instanceField(), "undefined", "instance field"); + shouldBe(staticField(), "undefined", "static field"); + shouldBe(staticBlock(), "undefined", "static block"); + shouldBe(privateField(), "undefined", "private field"); + shouldBe(computedField(), "undefined", "computed field"); + shouldBe(classExpression(), "undefined", "class expression"); + shouldBe(derivedClass(), "undefined", "derived class"); + shouldBe(classWithConstructor(), "undefined true", "class with constructor"); + shouldBe(arrowInArrow(), "undefined", "arrow function in arrow function"); + shouldBe(arrowInField(), "undefined", "arrow function in field"); + shouldBe(arrowInStaticBlock(), "undefined", "arrow function in static block"); + shouldBe(blockInStaticBlock(), "undefined", "block in static block"); + shouldBe(keyOfClassInField(), "undefined", "key of a class in a field"); + shouldBe(fieldOfClassInField(), "undefined", "field of a class in a field"); + shouldBe(fieldOfClassInStaticBlock(), "undefined", "field of a class in a static block"); + shouldBe(parameterOfArrowInField(), "undefined", "parameter of an arrow function in a field"); + shouldBe(evalInField(), "undefined", "eval in field"); + shouldBe(evalInStaticBlock(), "undefined", "eval in static block"); + } +} + +// The class is in an async arrow function in global code. The call must not throw. +{ + const asyncArrow = async () => { class A { x = typeof new.target; } return new A().x; }; + const asyncArrowWithAwait = async () => { await 1; class A { static x = typeof new.target; static y; static { A.y = typeof new.target; } } return A.x + " " + A.y; }; + const asyncArrowWithParameters = async (a = 1, ...rest) => { class A { x = typeof new.target; } return new A().x; }; + + shouldBeAsync(asyncArrow(), "undefined", "async arrow function"); + shouldBeAsync(asyncArrowWithAwait(), "undefined undefined", "async arrow function with await"); + shouldBeAsync(asyncArrowWithParameters(), "undefined", "async arrow function with parameters"); +} + +// The class is in an arrow function with parameters that are not simple. +{ + const arrowWithParameters = (a = 1, { b } = { b: 2 }, ...rest) => { class A { x = typeof new.target; static { A.y = typeof new.target; } } return new A().x + " " + A.y; }; + shouldBe(arrowWithParameters(), "undefined undefined", "arrow function with parameters"); +} + +// The class is in an arrow function in a function. The function does not save new.target for a static block. +{ + function staticBlockInArrowInFunction() { + return (() => { let r; class A { static { r = typeof new.target; } } return r; })(); + } + function fieldInArrowInFunction() { + return (() => { class A { x = typeof new.target; static y = typeof new.target; } return new A().x + " " + A.y; })(); + } + function Constructor() { + this.staticBlock = (() => { let r = 1; class A { static { r = new.target; } } return r; })(); + this.field = (() => { class A { x = new.target; } return new A().x; })(); + this.target = (() => new.target)(); + } + const method = { method() { return (() => { let r; class A { x = typeof new.target; static { r = typeof new.target; } } return new A().x + " " + r; })(); } }.method; + + for (let i = 0; i < 100; ++i) { + shouldBe(staticBlockInArrowInFunction(), "undefined", "static block, arrow function in function"); + shouldBe(new staticBlockInArrowInFunction() instanceof staticBlockInArrowInFunction, true, "static block, arrow function in constructor"); + shouldBe(fieldInArrowInFunction(), "undefined undefined", "field, arrow function in function"); + let object = new Constructor(); + shouldBe(object.staticBlock, undefined, "static block, arrow function in constructor"); + shouldBe(object.field, undefined, "field, arrow function in constructor"); + shouldBe(object.target, Constructor, "arrow function in constructor"); + shouldBe(method(), "undefined undefined", "arrow function in method"); + } +} + +// The class is in eval code. +{ + shouldBe((0, eval)("class A { x = typeof new.target; } new A().x"), "undefined", "field, indirect eval"); + shouldBe((0, eval)("class B { static x = typeof new.target; } B.x"), "undefined", "static field, indirect eval"); + shouldBe((0, eval)("var r; class C { static { r = typeof new.target; } } r"), "undefined", "static block, indirect eval"); + shouldBe((0, eval)("(() => { class A { x = typeof new.target; } return new A().x; })()"), "undefined", "arrow function, indirect eval"); + shouldBe(eval("class D { x = typeof new.target; } new D().x"), "undefined", "field, direct eval in global code"); + shouldBe((() => eval("class A { x = typeof new.target; static { A.y = typeof new.target; } } new A().x + ' ' + A.y"))(), "undefined undefined", "direct eval in arrow function"); + function directEvalInFunction() { + return eval("class A { x = new.target; static { A.y = new.target; } } [new A().x, A.y, new.target]"); + } + let [field, staticBlock, target] = new directEvalInFunction(); + shouldBe(field, undefined, "field, direct eval in constructor"); + shouldBe(staticBlock, undefined, "static block, direct eval in constructor"); + shouldBe(target, directEvalInFunction, "direct eval in constructor"); + shouldBe(new Function("return (() => { class A { x = typeof new.target; } return new A().x; })()")(), "undefined", "Function constructor"); +} + +// A function in a class element has its own new.target. A key and a heritage belong to the code around the class. +{ + const functionInField = () => { class A { f = function () { return new.target; }; } return new A().f; }; + const functionInStaticBlock = () => { let f; class A { static { f = function () { return new.target; }; } } return f; }; + function Keys() { + class A { [new.target.name] = 1; static [new.target.name + "Static"] = 2; [new.target.name + "Method"]() { } } + this.keys = Object.keys(new A()).concat(Object.keys(A), Object.getOwnPropertyNames(A.prototype)); + } + function Heritage() { + class A extends new.target.Base { } + this.result = new A() instanceof Heritage.Base; + } + Heritage.Base = class { }; + function KeysInArrow() { + this.keys = (() => { class A { [new.target.name] = typeof new.target; } let a = new A(); return Object.keys(a)[0] + " " + a.KeysInArrow; })(); + } + + for (let i = 0; i < 100; ++i) { + let f = functionInField(); + shouldBe(f(), undefined, "function in field, call"); + shouldBe(new f(), f, "function in field, construct"); + let g = functionInStaticBlock(); + shouldBe(g(), undefined, "function in static block, call"); + shouldBe(new g(), g, "function in static block, construct"); + shouldBe(new Keys().keys.join(), "Keys,KeysStatic,constructor,KeysMethod", "keys"); + shouldBe(new Heritage().result, true, "heritage"); + shouldBe(new KeysInArrow().keys, "KeysInArrow undefined", "key and field in arrow function in constructor"); + } +} diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h index 12d4a4264a7a..74cf1a0ba11c 100644 --- a/Source/JavaScriptCore/parser/ASTBuilder.h +++ b/Source/JavaScriptCore/parser/ASTBuilder.h @@ -189,9 +189,12 @@ class ASTBuilder { setExceptionLocation(node, start, divot, end); return node; } - ExpressionNode* createNewTargetExpr(const JSTokenLocation location) + // usesNewTargetOfThisCode is false for a class field initializer or a class static block that + // the parser parses in place. Their new.target is not the new.target of the code that this builds. + ExpressionNode* createNewTargetExpr(const JSTokenLocation location, bool usesNewTargetOfThisCode) { - usesNewTarget(); + if (usesNewTargetOfThisCode) + usesNewTarget(); return new (m_parserArena) NewTargetNode(location); } ExpressionNode* createImportMetaExpr(const JSTokenLocation& location, ExpressionNode* expr) { return new (m_parserArena) ImportMetaNode(location, expr); } diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp index d3f28f7d139f..47fb4c2d8ded 100644 --- a/Source/JavaScriptCore/parser/Parser.cpp +++ b/Source/JavaScriptCore/parser/Parser.cpp @@ -3370,7 +3370,9 @@ template TreeClassExpression Parser::parseClass(T SetForScope overrideParsingClassFieldInitializer(m_parserState.isParsingClassFieldInitializer, true); SetForScope maskAsync(m_parserState.classFieldInitMasksAsync, true); classScope->setExpectedSuperBinding(SuperBinding::Needed); + classScope->setIsParsingFieldInitializerInPlace(true); initializer = parseAssignmentExpression(context); + classScope->setIsParsingFieldInitializerInPlace(false); classScope->setExpectedSuperBinding(SuperBinding::NotNeeded); failIfFalse(initializer, "Cannot parse initializer for class field"); classScope->markLastUsedVariablesSetAsCaptured(usedVariablesSize); @@ -5483,11 +5485,16 @@ template TreeExpression Parser::parseMemberExpres bool isClassFieldInitializer = m_parserState.isParsingClassFieldInitializer; bool isFunctionEvalContextType = m_isInsideOrdinaryFunction && (closestOrdinaryFunctionScope->evalContextType() == EvalContextType::FunctionEvalContext || closestOrdinaryFunctionScope->evalContextType() == EvalContextType::InstanceFieldEvalContext); semanticFailIfFalse(currentScope()->isFunction() || currentScope()->isStaticBlock() || isFunctionEvalContextType || isClassFieldInitializer, "new.target is only valid inside functions or static blocks"); - if (currentScope()->isArrowFunction()) { + // The code around a class must not become a user of new.target because of a class element + // that parseClass() parses in place. An arrow function, or eval code, that uses new.target + // loads it from the scope of a function that saved it there. No function saves it for + // a new.target that it does not contain. + bool usesNewTargetOfClassElementParsedInPlace = isDirectlyInClassElementParsedInPlace(); + if (currentScope()->isArrowFunction() && !usesNewTargetOfClassElementParsedInPlace) { semanticFailIfFalse(!closestOrdinaryFunctionScope->isGlobalCode() || isFunctionEvalContextType || isClassFieldInitializer, "new.target is not valid inside arrow functions in global code"); currentScope()->setInnerArrowFunctionUsesNewTarget(); } - base = context.createNewTargetExpr(location); + base = context.createNewTargetExpr(location, !usesNewTargetOfClassElementParsedInPlace); newCount--; next(); } else { diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h index 96a6a5a833e2..4540269cd9ca 100644 --- a/Source/JavaScriptCore/parser/Parser.h +++ b/Source/JavaScriptCore/parser/Parser.h @@ -327,6 +327,10 @@ struct Scope { m_isClassScope = true; } + // True for a class scope while parseClass() parses one of its field initializers in place. + void setIsParsingFieldInitializerInPlace(bool isParsingFieldInitializerInPlace) { m_isParsingFieldInitializerInPlace = isParsingFieldInitializerInPlace; } + bool isParsingFieldInitializerInPlace() const { return m_isParsingFieldInitializerInPlace; } + bool isLexicalScope() const { return m_isLexicalScope; } bool usesEval() const { return m_usesEval; } bool usesImportMeta() const { return m_usesImportMeta; } @@ -1043,6 +1047,7 @@ struct Scope { bool m_isEvalContext : 1 { false }; bool m_hasNonSimpleParameterList : 1 { false }; bool m_isClassScope : 1 { false }; + bool m_isParsingFieldInitializerInPlace : 1 { false }; bool m_asyncFunctionBodyDoesNotUseAwait : 1 { false }; bool m_usesAwait : 1 { false }; int m_loopDepth { 0 }; @@ -1338,6 +1343,24 @@ class JSC_CACHE_LINE_ALIGNED Parser { return scope; } + // A class field initializer and a class static block are functions of their own at run time. + // parseClass() parses the source of each in place, with the scopes and the tree builder of the + // code around the class. That parse checks the syntax and finds the end. The function is parsed + // again, on its own, when it is compiled. This returns true when the current position is in + // such a class element and not in an arrow function inside it. The code there uses the + // new.target of the class element, and not the new.target of the code around the class. + bool isDirectlyInClassElementParsedInPlace() + { + for (Scope* scope = currentScope(); scope; scope = scope->containingScope()) { + // The static block that this parser compiles is the outermost scope. + if (scope->isFunctionBoundary()) + return scope->isStaticBlockBoundary() && scope->containingScope(); + if (scope->isParsingFieldInitializerInPlace()) + return true; + } + return false; + } + Scope* pushScope() { ImplementationVisibility implementationVisibility = m_implementationVisibility; diff --git a/Source/JavaScriptCore/parser/SyntaxChecker.h b/Source/JavaScriptCore/parser/SyntaxChecker.h index ef23c234f976..c98791041e9c 100644 --- a/Source/JavaScriptCore/parser/SyntaxChecker.h +++ b/Source/JavaScriptCore/parser/SyntaxChecker.h @@ -168,7 +168,7 @@ class SyntaxChecker { ExpressionType createImportExpr(const JSTokenLocation&, ExpressionType, ExpressionType, bool, int, int, int) { return ImportExpr; } ExpressionType createThisExpr(const JSTokenLocation&) { return ThisExpr; } ExpressionType createSuperExpr(const JSTokenLocation&) { return SuperExpr; } - ExpressionType createNewTargetExpr(const JSTokenLocation&) { return NewTargetExpr; } + ExpressionType createNewTargetExpr(const JSTokenLocation&, bool) { return NewTargetExpr; } ExpressionType createImportMetaExpr(const JSTokenLocation&, ExpressionType) { return ImportMetaExpr; } ALWAYS_INLINE bool isMetaProperty(ExpressionType type) { return type & MetaPropertyBit; } ALWAYS_INLINE bool isNewTarget(ExpressionType type) { return type == NewTargetExpr; } From e283f89cf3d3931891eeca4bf22232eac94911a5 Mon Sep 17 00:00:00 2001 From: robobun <117481402+robobun@users.noreply.github.com> Date: Sun, 13 Sep 2026 18:39:36 +0000 Subject: [PATCH 2/2] Run each case of the new.target test once The change is in the parser, so a case passes or fails on its first run. No loop count is needed. --- ...lass-field-initializer-and-static-block.js | 76 +++++++++---------- 1 file changed, 35 insertions(+), 41 deletions(-) diff --git a/JSTests/stress/new-target-in-class-field-initializer-and-static-block.js b/JSTests/stress/new-target-in-class-field-initializer-and-static-block.js index 9819a73ba4d0..9a25f4f21a9f 100644 --- a/JSTests/stress/new-target-in-class-field-initializer-and-static-block.js +++ b/JSTests/stress/new-target-in-class-field-initializer-and-static-block.js @@ -37,26 +37,24 @@ function shouldBeAsync(promise, expected, message) { const evalInField = () => { class A { x = eval("typeof new.target"); } return new A().x; }; const evalInStaticBlock = () => { let r; class A { static { r = eval("typeof new.target"); } } return r; }; - for (let i = 0; i < 100; ++i) { - shouldBe(instanceField(), "undefined", "instance field"); - shouldBe(staticField(), "undefined", "static field"); - shouldBe(staticBlock(), "undefined", "static block"); - shouldBe(privateField(), "undefined", "private field"); - shouldBe(computedField(), "undefined", "computed field"); - shouldBe(classExpression(), "undefined", "class expression"); - shouldBe(derivedClass(), "undefined", "derived class"); - shouldBe(classWithConstructor(), "undefined true", "class with constructor"); - shouldBe(arrowInArrow(), "undefined", "arrow function in arrow function"); - shouldBe(arrowInField(), "undefined", "arrow function in field"); - shouldBe(arrowInStaticBlock(), "undefined", "arrow function in static block"); - shouldBe(blockInStaticBlock(), "undefined", "block in static block"); - shouldBe(keyOfClassInField(), "undefined", "key of a class in a field"); - shouldBe(fieldOfClassInField(), "undefined", "field of a class in a field"); - shouldBe(fieldOfClassInStaticBlock(), "undefined", "field of a class in a static block"); - shouldBe(parameterOfArrowInField(), "undefined", "parameter of an arrow function in a field"); - shouldBe(evalInField(), "undefined", "eval in field"); - shouldBe(evalInStaticBlock(), "undefined", "eval in static block"); - } + shouldBe(instanceField(), "undefined", "instance field"); + shouldBe(staticField(), "undefined", "static field"); + shouldBe(staticBlock(), "undefined", "static block"); + shouldBe(privateField(), "undefined", "private field"); + shouldBe(computedField(), "undefined", "computed field"); + shouldBe(classExpression(), "undefined", "class expression"); + shouldBe(derivedClass(), "undefined", "derived class"); + shouldBe(classWithConstructor(), "undefined true", "class with constructor"); + shouldBe(arrowInArrow(), "undefined", "arrow function in arrow function"); + shouldBe(arrowInField(), "undefined", "arrow function in field"); + shouldBe(arrowInStaticBlock(), "undefined", "arrow function in static block"); + shouldBe(blockInStaticBlock(), "undefined", "block in static block"); + shouldBe(keyOfClassInField(), "undefined", "key of a class in a field"); + shouldBe(fieldOfClassInField(), "undefined", "field of a class in a field"); + shouldBe(fieldOfClassInStaticBlock(), "undefined", "field of a class in a static block"); + shouldBe(parameterOfArrowInField(), "undefined", "parameter of an arrow function in a field"); + shouldBe(evalInField(), "undefined", "eval in field"); + shouldBe(evalInStaticBlock(), "undefined", "eval in static block"); } // The class is in an async arrow function in global code. The call must not throw. @@ -91,16 +89,14 @@ function shouldBeAsync(promise, expected, message) { } const method = { method() { return (() => { let r; class A { x = typeof new.target; static { r = typeof new.target; } } return new A().x + " " + r; })(); } }.method; - for (let i = 0; i < 100; ++i) { - shouldBe(staticBlockInArrowInFunction(), "undefined", "static block, arrow function in function"); - shouldBe(new staticBlockInArrowInFunction() instanceof staticBlockInArrowInFunction, true, "static block, arrow function in constructor"); - shouldBe(fieldInArrowInFunction(), "undefined undefined", "field, arrow function in function"); - let object = new Constructor(); - shouldBe(object.staticBlock, undefined, "static block, arrow function in constructor"); - shouldBe(object.field, undefined, "field, arrow function in constructor"); - shouldBe(object.target, Constructor, "arrow function in constructor"); - shouldBe(method(), "undefined undefined", "arrow function in method"); - } + shouldBe(staticBlockInArrowInFunction(), "undefined", "static block, arrow function in function"); + shouldBe(new staticBlockInArrowInFunction() instanceof staticBlockInArrowInFunction, true, "static block, arrow function in constructor"); + shouldBe(fieldInArrowInFunction(), "undefined undefined", "field, arrow function in function"); + let object = new Constructor(); + shouldBe(object.staticBlock, undefined, "static block, arrow function in constructor"); + shouldBe(object.field, undefined, "field, arrow function in constructor"); + shouldBe(object.target, Constructor, "arrow function in constructor"); + shouldBe(method(), "undefined undefined", "arrow function in method"); } // The class is in eval code. @@ -138,15 +134,13 @@ function shouldBeAsync(promise, expected, message) { this.keys = (() => { class A { [new.target.name] = typeof new.target; } let a = new A(); return Object.keys(a)[0] + " " + a.KeysInArrow; })(); } - for (let i = 0; i < 100; ++i) { - let f = functionInField(); - shouldBe(f(), undefined, "function in field, call"); - shouldBe(new f(), f, "function in field, construct"); - let g = functionInStaticBlock(); - shouldBe(g(), undefined, "function in static block, call"); - shouldBe(new g(), g, "function in static block, construct"); - shouldBe(new Keys().keys.join(), "Keys,KeysStatic,constructor,KeysMethod", "keys"); - shouldBe(new Heritage().result, true, "heritage"); - shouldBe(new KeysInArrow().keys, "KeysInArrow undefined", "key and field in arrow function in constructor"); - } + let f = functionInField(); + shouldBe(f(), undefined, "function in field, call"); + shouldBe(new f(), f, "function in field, construct"); + let g = functionInStaticBlock(); + shouldBe(g(), undefined, "function in static block, call"); + shouldBe(new g(), g, "function in static block, construct"); + shouldBe(new Keys().keys.join(), "Keys,KeysStatic,constructor,KeysMethod", "keys"); + shouldBe(new Heritage().result, true, "heritage"); + shouldBe(new KeysInArrow().keys, "KeysInArrow undefined", "key and field in arrow function in constructor"); }