Title: [182171] trunk
Revision
182171
Author
[email protected]
Date
2015-03-30 18:59:31 -0700 (Mon, 30 Mar 2015)

Log Message

Extending null should set __proto__ to null
https://bugs.webkit.org/show_bug.cgi?id=142882

Reviewed by Geoffrey Garen and Benjamin Poulain.

Source/_javascript_Core:

Set Derived.prototype.__proto__ to null when extending null.

* bytecompiler/NodesCodegen.cpp:
(JSC::ClassExprNode::emitBytecode):

LayoutTests:

Added more test cases for extending from null, and added checks for prototypes.

Also rebaselined existing tests.

* js/class-syntax-call-expected.txt:
* js/class-syntax-extends-expected.txt:
* js/class-syntax-super-expected.txt:
* js/script-tests/class-syntax-call.js:
* js/script-tests/class-syntax-extends.js:
* js/script-tests/class-syntax-super.js:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (182170 => 182171)


--- trunk/LayoutTests/ChangeLog	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/LayoutTests/ChangeLog	2015-03-31 01:59:31 UTC (rev 182171)
@@ -1,3 +1,21 @@
+2015-03-30  Ryosuke Niwa  <[email protected]>
+
+        Extending null should set __proto__ to null
+        https://bugs.webkit.org/show_bug.cgi?id=142882
+
+        Reviewed by Geoffrey Garen and Benjamin Poulain.
+
+        Added more test cases for extending from null, and added checks for prototypes.
+
+        Also rebaselined existing tests.
+
+        * js/class-syntax-call-expected.txt:
+        * js/class-syntax-extends-expected.txt:
+        * js/class-syntax-super-expected.txt:
+        * js/script-tests/class-syntax-call.js:
+        * js/script-tests/class-syntax-extends.js:
+        * js/script-tests/class-syntax-super.js:
+
 2015-03-30  Alex Christensen  <[email protected]>
 
         [Content Extensions] Correctly handle regular expressions matching everything

Modified: trunk/LayoutTests/js/class-syntax-call-expected.txt (182170 => 182171)


--- trunk/LayoutTests/js/class-syntax-call-expected.txt	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/LayoutTests/js/class-syntax-call-expected.txt	2015-03-31 01:59:31 UTC (rev 182171)
@@ -9,7 +9,7 @@
 PASS B() threw exception TypeError: Cannot call a class constructor.
 PASS new (class { constructor() {} })() did not throw exception.
 PASS (class { constructor() {} })() threw exception TypeError: Cannot call a class constructor.
-PASS new (class extends null { constructor() { super() } })() did not throw exception.
+PASS new (class extends null { constructor() { super() } })() threw exception TypeError: undefined is not an object (evaluating 'super()').
 PASS (class extends null { constructor() { super() } })() threw exception TypeError: Cannot call a class constructor.
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/js/class-syntax-extends-expected.txt (182170 => 182171)


--- trunk/LayoutTests/js/class-syntax-extends-expected.txt	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/LayoutTests/js/class-syntax-extends-expected.txt	2015-03-31 01:59:31 UTC (rev 182171)
@@ -4,7 +4,10 @@
 
 
 PASS (new Base) instanceof Base is true
+PASS Object.getPrototypeOf(new Base) is Base.prototype
 PASS (new Derived) instanceof Derived is true
+PASS Object.getPrototypeOf(new Derived) is Derived.prototype
+PASS Object.getPrototypeOf(Derived.prototype) is Base.prototype
 PASS (new Derived).baseMethod() is "base"
 PASS (new Derived).overridenMethod() is "derived"
 PASS Derived.staticBaseMethod() is "base"
@@ -15,7 +18,9 @@
 PASS x = class extends Base { } did not throw exception.
 PASS x = class extends Base { constructor() { } } did not throw exception.
 PASS x.__proto__ is Base
+PASS Object.getPrototypeOf(x) is Base
 PASS x.prototype.__proto__ is Base.prototype
+PASS Object.getPrototypeOf(x.prototype) is Base.prototype
 PASS x = class extends null { constructor() { } }; x.__proto__ is Function.prototype
 PASS x.__proto__ is Function.prototype
 PASS x = class extends 3 { constructor() { } }; x.__proto__ threw exception TypeError: The superclass is not an object..
@@ -47,6 +52,21 @@
 PASS namespace = {}; namespace.A = class { constructor() { } }; namespace.B = class extends new namespace.A() { constructor() { } } threw exception TypeError: The superclass's prototype is not an object..
 PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (x++, namespace.A) { constructor() { } } } catch (e) { } x is 2
 PASS x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (namespace.A, x++) { constructor() { } } } catch (e) { } x is 2
+PASS Object.getPrototypeOf((class { constructor () { } }).prototype) is Object.prototype
+PASS Object.getPrototypeOf((class extends null { constructor () { super(); } }).prototype) is null
+PASS new (class extends undefined { constructor () { this } }) threw exception ReferenceError: Cannot access uninitialized variable..
+PASS new (class extends undefined { constructor () { super(); } }) threw exception TypeError: undefined is not an object (evaluating 'super()').
+PASS x = {}; new (class extends undefined { constructor () { return x; } }) is x
+PASS y = 12; new (class extends undefined { constructor () { return y; } }) threw exception TypeError: Cannot return a non-object type in the constructor of a derived class..
+PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
+PASS new (class extends null { constructor () { this; } }) threw exception ReferenceError: Cannot access uninitialized variable..
+PASS new (class extends null { constructor () { super(); } }) threw exception TypeError: undefined is not an object (evaluating 'super()').
+PASS x = {}; new (class extends null { constructor () { return x } }) is x
+PASS y = 12; new (class extends null { constructor () { return y; } }) threw exception TypeError: Cannot return a non-object type in the constructor of a derived class..
+PASS class x {}; new (class extends null { constructor () { return new x; } }) instanceof x is true
+PASS x = null; Object.getPrototypeOf((class extends x { }).prototype) is null
+PASS Object.prototype.isPrototypeOf(class { }) is true
+PASS Function.prototype.isPrototypeOf(class { }) is true
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/js/class-syntax-super-expected.txt (182170 => 182171)


--- trunk/LayoutTests/js/class-syntax-super-expected.txt	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/LayoutTests/js/class-syntax-super-expected.txt	2015-03-31 01:59:31 UTC (rev 182171)
@@ -31,12 +31,12 @@
 PASS new (class extends Base { constructor() { } }) threw exception ReferenceError: Cannot access uninitialized variable..
 PASS new (class extends Base { constructor() { return 1; } }) threw exception TypeError: Cannot return a non-object type in the constructor of a derived class..
 PASS new (class extends null { constructor() { return undefined } }) threw exception ReferenceError: Cannot access uninitialized variable..
-PASS new (class extends null { constructor() { super(); return undefined } }) instanceof Object is true
+PASS new (class extends null { constructor() { super(); return undefined } }) threw exception TypeError: undefined is not an object (evaluating 'super()').
 PASS x = { }; new (class extends null { constructor() { return x } }); is x
 PASS x instanceof Object is true
 PASS new (class extends null { constructor() { } }) threw exception ReferenceError: Cannot access uninitialized variable..
 PASS new (class extends null { constructor() { return 1; } }) threw exception TypeError: Cannot return a non-object type in the constructor of a derived class..
-PASS new (class extends null { constructor() { super() } }) did not throw exception.
+PASS new (class extends null { constructor() { super() } }) threw exception TypeError: undefined is not an object (evaluating 'super()').
 PASS new (class { constructor() { super() } }) threw exception SyntaxError: Cannot call super() in a base class constructor..
 PASS function x() { super(); } threw exception SyntaxError: Cannot call super() outside of a class constructor..
 PASS new (class extends Object { constructor() { function x() { super() } } }) threw exception SyntaxError: Cannot call super() outside of a class constructor..

Modified: trunk/LayoutTests/js/script-tests/class-syntax-call.js (182170 => 182171)


--- trunk/LayoutTests/js/script-tests/class-syntax-call.js	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/LayoutTests/js/script-tests/class-syntax-call.js	2015-03-31 01:59:31 UTC (rev 182171)
@@ -9,7 +9,7 @@
 shouldThrow('B()', '"TypeError: Cannot call a class constructor"');
 shouldNotThrow('new (class { constructor() {} })()');
 shouldThrow('(class { constructor() {} })()', '"TypeError: Cannot call a class constructor"');
-shouldNotThrow('new (class extends null { constructor() { super() } })()');
+shouldThrow('new (class extends null { constructor() { super() } })()', '"TypeError: undefined is not an object (evaluating \'super()\')"');
 shouldThrow('(class extends null { constructor() { super() } })()', '"TypeError: Cannot call a class constructor"');
 
 var successfullyParsed = true;

Modified: trunk/LayoutTests/js/script-tests/class-syntax-extends.js (182170 => 182171)


--- trunk/LayoutTests/js/script-tests/class-syntax-extends.js	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/LayoutTests/js/script-tests/class-syntax-extends.js	2015-03-31 01:59:31 UTC (rev 182171)
@@ -16,7 +16,10 @@
 }
 
 shouldBeTrue('(new Base) instanceof Base');
+shouldBe('Object.getPrototypeOf(new Base)', 'Base.prototype');
 shouldBeTrue('(new Derived) instanceof Derived');
+shouldBe('Object.getPrototypeOf(new Derived)', 'Derived.prototype');
+shouldBe('Object.getPrototypeOf(Derived.prototype)', 'Base.prototype');
 shouldBe('(new Derived).baseMethod()', '"base"');
 shouldBe('(new Derived).overridenMethod()', '"derived"');
 shouldBe('Derived.staticBaseMethod()', '"base"');
@@ -28,7 +31,9 @@
 shouldNotThrow('x = class extends Base { }');
 shouldNotThrow('x = class extends Base { constructor() { } }');
 shouldBe('x.__proto__', 'Base');
+shouldBe('Object.getPrototypeOf(x)', 'Base');
 shouldBe('x.prototype.__proto__', 'Base.prototype');
+shouldBe('Object.getPrototypeOf(x.prototype)', 'Base.prototype');
 shouldBe('x = class extends null { constructor() { } }; x.__proto__', 'Function.prototype');
 shouldBe('x.__proto__', 'Function.prototype');
 shouldThrow('x = class extends 3 { constructor() { } }; x.__proto__', '"TypeError: The superclass is not an object."');
@@ -63,4 +68,20 @@
 shouldBe('x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (x++, namespace.A) { constructor() { } } } catch (e) { } x', '2');
 shouldBe('x = 1; namespace = {}; namespace.A = class { constructor() { } }; try { namespace.B = class extends (namespace.A, x++) { constructor() { } } } catch (e) { } x', '2');
 
+shouldBe('Object.getPrototypeOf((class { constructor () { } }).prototype)', 'Object.prototype');
+shouldBe('Object.getPrototypeOf((class extends null { constructor () { super(); } }).prototype)', 'null');
+shouldThrow('new (class extends undefined { constructor () { this } })', '"ReferenceError: Cannot access uninitialized variable."');
+shouldThrow('new (class extends undefined { constructor () { super(); } })', '"TypeError: undefined is not an object (evaluating \'super()\')"');
+shouldBe('x = {}; new (class extends undefined { constructor () { return x; } })', 'x');
+shouldThrow('y = 12; new (class extends undefined { constructor () { return y; } })', '"TypeError: Cannot return a non-object type in the constructor of a derived class."');
+shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
+shouldThrow('new (class extends null { constructor () { this; } })', '"ReferenceError: Cannot access uninitialized variable."');
+shouldThrow('new (class extends null { constructor () { super(); } })', '"TypeError: undefined is not an object (evaluating \'super()\')"');
+shouldBe('x = {}; new (class extends null { constructor () { return x } })', 'x');
+shouldThrow('y = 12; new (class extends null { constructor () { return y; } })', '"TypeError: Cannot return a non-object type in the constructor of a derived class."');
+shouldBeTrue ('class x {}; new (class extends null { constructor () { return new x; } }) instanceof x');
+shouldBe('x = null; Object.getPrototypeOf((class extends x { }).prototype)', 'null');
+shouldBeTrue('Object.prototype.isPrototypeOf(class { })');
+shouldBeTrue('Function.prototype.isPrototypeOf(class { })');
+
 var successfullyParsed = true;

Modified: trunk/LayoutTests/js/script-tests/class-syntax-super.js (182170 => 182171)


--- trunk/LayoutTests/js/script-tests/class-syntax-super.js	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/LayoutTests/js/script-tests/class-syntax-super.js	2015-03-31 01:59:31 UTC (rev 182171)
@@ -56,12 +56,12 @@
 shouldThrow('new (class extends Base { constructor() { } })', '"ReferenceError: Cannot access uninitialized variable."');
 shouldThrow('new (class extends Base { constructor() { return 1; } })', '"TypeError: Cannot return a non-object type in the constructor of a derived class."');
 shouldThrow('new (class extends null { constructor() { return undefined } })');
-shouldBeTrue('new (class extends null { constructor() { super(); return undefined } }) instanceof Object');
+shouldThrow('new (class extends null { constructor() { super(); return undefined } })', '"TypeError: undefined is not an object (evaluating \'super()\')"');
 shouldBe('x = { }; new (class extends null { constructor() { return x } });', 'x');
 shouldBeTrue('x instanceof Object');
 shouldThrow('new (class extends null { constructor() { } })', '"ReferenceError: Cannot access uninitialized variable."');
 shouldThrow('new (class extends null { constructor() { return 1; } })', '"TypeError: Cannot return a non-object type in the constructor of a derived class."');
-shouldNotThrow('new (class extends null { constructor() { super() } })');
+shouldThrow('new (class extends null { constructor() { super() } })', '"TypeError: undefined is not an object (evaluating \'super()\')"');
 shouldThrow('new (class { constructor() { super() } })', '"SyntaxError: Cannot call super() in a base class constructor."');
 shouldThrow('function x() { super(); }', '"SyntaxError: Cannot call super() outside of a class constructor."');
 shouldThrow('new (class extends Object { constructor() { function x() { super() } } })', '"SyntaxError: Cannot call super() outside of a class constructor."');

Modified: trunk/Source/_javascript_Core/ChangeLog (182170 => 182171)


--- trunk/Source/_javascript_Core/ChangeLog	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-03-31 01:59:31 UTC (rev 182171)
@@ -1,3 +1,15 @@
+2015-03-30  Ryosuke Niwa  <[email protected]>
+
+        Extending null should set __proto__ to null
+        https://bugs.webkit.org/show_bug.cgi?id=142882
+
+        Reviewed by Geoffrey Garen and Benjamin Poulain.
+
+        Set Derived.prototype.__proto__ to null when extending null.
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ClassExprNode::emitBytecode):
+
 2015-03-30  Mark Lam  <[email protected]>
 
         REGRESSION (r181993): inspector-protocol/debugger/setBreakpoint-dfg-and-modify-local.html crashes.

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (182170 => 182171)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-03-31 01:21:21 UTC (rev 182170)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2015-03-31 01:59:31 UTC (rev 182171)
@@ -2865,6 +2865,9 @@
     prototype = generator.emitGetById(generator.newTemporary(), constructor.get(), generator.propertyNames().prototype);
 
     if (superclass) {
+        RefPtr<RegisterID> protoParent = generator.newTemporary();
+        generator.emitLoad(protoParent.get(), jsNull());
+
         RefPtr<RegisterID> tempRegister = generator.newTemporary();
         RefPtr<Label> superclassIsNullLabel = generator.newLabel();
         generator.emitJumpIfTrue(generator.emitUnaryOp(op_eq_null, tempRegister.get(), superclass.get()), superclassIsNullLabel.get());
@@ -2874,8 +2877,6 @@
         generator.emitJumpIfTrue(generator.emitIsObject(tempRegister.get(), superclass.get()), superclassIsObjectLabel.get());
         generator.emitThrowTypeError(ASCIILiteral("The superclass is not an object."));
         generator.emitLabel(superclassIsObjectLabel.get());
-
-        RefPtr<RegisterID> protoParent = generator.newTemporary();
         generator.emitGetById(protoParent.get(), superclass.get(), generator.propertyNames().prototype);
 
         RefPtr<Label> protoParentIsObjectOrNullLabel = generator.newLabel();
@@ -2884,9 +2885,9 @@
         generator.emitLabel(protoParentIsObjectOrNullLabel.get());
 
         generator.emitDirectPutById(constructor.get(), generator.propertyNames().underscoreProto, superclass.get(), PropertyNode::Unknown);
+        generator.emitLabel(superclassIsNullLabel.get());
         generator.emitDirectPutById(prototype.get(), generator.propertyNames().underscoreProto, protoParent.get(), PropertyNode::Unknown);
 
-        generator.emitLabel(superclassIsNullLabel.get());
         emitPutHomeObject(generator, constructor.get(), prototype.get());
     }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to