Title: [187108] trunk/Source/_javascript_Core
Revision
187108
Author
commit-qu...@webkit.org
Date
2015-07-21 11:18:42 -0700 (Tue, 21 Jul 2015)

Log Message

Add support for the new.target syntax.
https://bugs.webkit.org/show_bug.cgi?id=147051

Patch by Keith Miller <keith_mil...@apple.com> on 2015-07-21
Reviewed by Yusuke Suzuki.

Add support for new.target. Essentially the implementation is, before constructor calls,
the target of a "new" is placed where "this" noramlly goes in the calling convention.
Then in the constructor before object is initialized we move the target of the "new"
into a local variable.

* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::BytecodeGenerator):
* bytecompiler/NodesCodegen.cpp:
(JSC::NewTargetNode::emitBytecode):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::newTargetExpr):
* parser/NodeConstructors.h:
(JSC::NewTargetNode::NewTargetNode):
* parser/Nodes.h:
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseMemberExpression):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::newTargetExpr):
* runtime/CommonIdentifiers.h:
* tests/stress/new-target.js: Added.
(test):
(call):
(Constructor.subCall):
(Constructor.SubConstructor):
(Constructor):
(noAssign):
(doWeirdThings):
(SuperClass):
(SubClass):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (187107 => 187108)


--- trunk/Source/_javascript_Core/ChangeLog	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-07-21 18:18:42 UTC (rev 187108)
@@ -1,3 +1,40 @@
+2015-07-21  Keith Miller  <keith_mil...@apple.com>
+
+        Add support for the new.target syntax.
+        https://bugs.webkit.org/show_bug.cgi?id=147051
+
+        Reviewed by Yusuke Suzuki.
+
+        Add support for new.target. Essentially the implementation is, before constructor calls,
+        the target of a "new" is placed where "this" noramlly goes in the calling convention.
+        Then in the constructor before object is initialized we move the target of the "new"
+        into a local variable.
+
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::BytecodeGenerator):
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::NewTargetNode::emitBytecode):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::newTargetExpr):
+        * parser/NodeConstructors.h:
+        (JSC::NewTargetNode::NewTargetNode):
+        * parser/Nodes.h:
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseMemberExpression):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::newTargetExpr):
+        * runtime/CommonIdentifiers.h:
+        * tests/stress/new-target.js: Added.
+        (test):
+        (call):
+        (Constructor.subCall):
+        (Constructor.SubConstructor):
+        (Constructor):
+        (noAssign):
+        (doWeirdThings):
+        (SuperClass):
+        (SubClass):
+
 2015-07-20  Saam barati  <saambara...@gmail.com>
 
         "let" scoping introduced incoherent story about symbol table cloning

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp (187107 => 187108)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.cpp	2015-07-21 18:18:42 UTC (rev 187108)
@@ -500,10 +500,10 @@
         }
     }
     
+    m_newTargetRegister = addVar();
     if (isConstructor()) {
+        emitMove(m_newTargetRegister, &m_thisRegister);
         if (constructorKind() == ConstructorKind::Derived) {
-            m_newTargetRegister = addVar();
-            emitMove(m_newTargetRegister, &m_thisRegister);
             emitMoveEmptyValue(&m_thisRegister);
         } else
             emitCreateThis(&m_thisRegister);

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (187107 => 187108)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-07-21 18:18:42 UTC (rev 187108)
@@ -185,6 +185,16 @@
     return generator.emitGetById(generator.newTemporary(), homeObject.get(), generator.propertyNames().underscoreProto);
 }
 
+// ------------------------------ NewTargetNode ----------------------------------
+
+RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (dst == generator.ignoredResult())
+        return nullptr;
+
+    return generator.moveToDestinationIfNeeded(dst, generator.newTarget());
+}
+
 // ------------------------------ ResolveNode ----------------------------------
 
 bool ResolveNode::isPure(BytecodeGenerator& generator) const

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (187107 => 187108)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2015-07-21 18:18:42 UTC (rev 187108)
@@ -177,6 +177,10 @@
     {
         return new (m_parserArena) SuperNode(location);
     }
+    ExpressionNode* newTargetExpr(const JSTokenLocation location)
+    {
+        return new (m_parserArena) NewTargetNode(location);
+    }
     ExpressionNode* createResolve(const JSTokenLocation& location, const Identifier* ident, const JSTextPosition& start)
     {
         if (m_vm->propertyNames->arguments == *ident)

Modified: trunk/Source/_javascript_Core/parser/NodeConstructors.h (187107 => 187108)


--- trunk/Source/_javascript_Core/parser/NodeConstructors.h	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/parser/NodeConstructors.h	2015-07-21 18:18:42 UTC (rev 187108)
@@ -170,6 +170,11 @@
     {
     }
 
+    inline NewTargetNode::NewTargetNode(const JSTokenLocation& location)
+        : ExpressionNode(location)
+    {
+    }
+
     inline ResolveNode::ResolveNode(const JSTokenLocation& location, const Identifier& ident, const JSTextPosition& start)
         : ExpressionNode(location)
         , m_ident(ident)

Modified: trunk/Source/_javascript_Core/parser/Nodes.h (187107 => 187108)


--- trunk/Source/_javascript_Core/parser/Nodes.h	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/parser/Nodes.h	2015-07-21 18:18:42 UTC (rev 187108)
@@ -547,6 +547,14 @@
         virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
     };
 
+    class NewTargetNode final : public ExpressionNode {
+    public:
+        NewTargetNode(const JSTokenLocation&);
+
+    private:
+        virtual RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
+    };
+
     class ResolveNode : public ExpressionNode {
     public:
         ResolveNode(const JSTokenLocation&, const Identifier&, const JSTextPosition& start);

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (187107 => 187108)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2015-07-21 18:18:42 UTC (rev 187108)
@@ -2883,11 +2883,28 @@
     bool baseIsSuper = false;
 #endif
 
+    bool baseIsNewTarget = false;
+    if (newCount && match(DOT)) {
+        next();
+        if (match(IDENT)) {
+            const Identifier* ident = m_token.m_data.ident;
+            if (m_vm->propertyNames->target == *ident) {
+                semanticFailIfFalse(currentScope()->isFunction(), "new.target is only valid inside functions");
+                baseIsNewTarget = true;
+                base = context.newTargetExpr(location);
+                newCount--;
+                next();
+            } else
+                failWithMessage("\"new.\" can only followed with target");
+        } else
+            failDueToUnexpectedToken();
+    }
+
     if (baseIsSuper) {
         base = context.superExpr(location);
         next();
         currentScope()->setNeedsSuperBinding();
-    } else
+    } else if (!baseIsNewTarget)
         base = parsePrimaryExpression(context);
 
     failIfFalse(base, "Cannot parse base _expression_");

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (187107 => 187108)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2015-07-21 18:18:42 UTC (rev 187108)
@@ -74,7 +74,7 @@
         ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr,
         FunctionExpr, ClassExpr, SuperExpr, BracketExpr, DotExpr, CallExpr,
         NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
-        ConditionalExpr, AssignmentExpr, TypeofExpr,
+        ConditionalExpr, AssignmentExpr, TypeofExpr, NewTargetExpr,
         DeleteExpr, ArrayLiteralExpr, BindingDestructuring,
         ArrayDestructuring, ObjectDestructuring, SourceElementsResult,
         FunctionBodyResult, SpreadExpr, ArgumentsResult,
@@ -154,6 +154,7 @@
     ExpressionType createVoid(const JSTokenLocation&, ExpressionType) { return UnaryExpr; }
     ExpressionType thisExpr(const JSTokenLocation&, ThisTDZMode) { return ThisExpr; }
     ExpressionType superExpr(const JSTokenLocation&) { return SuperExpr; }
+    ExpressionType newTargetExpr(const JSTokenLocation&) { return NewTargetExpr; }
     ExpressionType createResolve(const JSTokenLocation&, const Identifier*, int) { return ResolveExpr; }
     ExpressionType createObjectLiteral(const JSTokenLocation&) { return ObjectLiteralExpr; }
     ExpressionType createObjectLiteral(const JSTokenLocation&, int) { return ObjectLiteralExpr; }

Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (187107 => 187108)


--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2015-07-21 17:14:00 UTC (rev 187107)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2015-07-21 18:18:42 UTC (rev 187108)
@@ -166,6 +166,7 @@
     macro(sourceCode) \
     macro(stack) \
     macro(subarray) \
+    macro(target) \
     macro(test) \
     macro(then) \
     macro(toExponential) \

Added: trunk/Source/_javascript_Core/tests/stress/new-target.js (0 => 187108)


--- trunk/Source/_javascript_Core/tests/stress/new-target.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/new-target.js	2015-07-21 18:18:42 UTC (rev 187108)
@@ -0,0 +1,79 @@
+var passed = true;
+try {
+    eval("new.target;");
+    passed = false;
+} catch(e) {}
+
+test(passed, true, "new.target cannot be called in global scope");
+
+// Test without class syntax
+
+function test(result, expected, message) {
+    if (result !== expected)
+        throw "Error: " + message + ". was: " + result + " wanted: " + expected;
+}
+
+function call() {
+    test(new.target, undefined, "new.target should be undefined in a function call");
+}
+call();
+
+function Constructor() {
+    test(new.target, Constructor, "new.target should be the same as constructor");
+    function subCall() {
+        test(new.target, undefined, "new.target should be undefined in a sub function call");
+    }
+    subCall();
+
+    function SubConstructor() {
+        test(new.target, SubConstructor, "new.target should be subConstructor");
+    }
+    new SubConstructor();
+
+}
+new Constructor();
+
+function noAssign() {
+    new.target = 1;
+}
+
+try {
+    new noAssign();
+    passed = false;
+} catch(e) { }
+try {
+    noAssign();
+    passed = false;
+} catch(e) { }
+
+test(passed, true, "new.target should not be a reference");
+
+// This is mostly to test that calling new on new.target deos the right thing.
+function doWeirdThings(arg) {
+    if (new.target) {
+        if (arg)
+            this.value = new.target(1);
+        else
+            this.value = new new.target(true);
+    } else
+        return arg;
+}
+
+test(new doWeirdThings(false).value.value, 1, "calling new on new.target did something weird");
+
+// Test with class syntax
+
+class SuperClass {
+    constructor() {
+        this.target = new.target;
+    }
+}
+
+class SubClass extends SuperClass {
+    constructor() {
+        super();
+    }
+}
+
+test(new SuperClass().target, SuperClass, "new.target should be the same as the class constructor");
+test(new SubClass().target, SubClass, "new.target should not change when passed through super()");
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to