Changeset 198042 in webkit
- Timestamp:
- Mar 11, 2016, 1:08:08 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 21 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r198039 r198042 1 2016-03-11 Mark Lam <mark.lam@apple.com> 2 3 Implement Function.name and Function#toString for ES6 class. 4 https://bugs.webkit.org/show_bug.cgi?id=155336 5 6 Reviewed by Geoffrey Garen. 7 8 * js/class-syntax-name-expected.txt: 9 * js/script-tests/class-syntax-name.js: 10 (shouldBe): 11 (shouldBeTrue): 12 - Rebased expected result. 13 14 * js/function-toString-vs-name.html: 15 * js/script-tests/function-toString-vs-name.js: 16 - Added new tests for class. 17 18 * platform/mac/inspector/model/remote-object-expected.txt: 19 - Rebased expected result. 20 1 21 2016-03-11 Ryan Haddad <ryanhaddad@apple.com> 2 22 -
trunk/LayoutTests/js/class-syntax-name-expected.txt
r187680 r198042 13 13 PASS class A { constructor() {} } 14 14 PASS 'use strict'; class A { constructor() {} } 15 PASS class A { constructor() {} }; A.toString():::' function A() {}'16 PASS 'use strict'; class A { constructor() {} }; A.toString():::' function A() {}'15 PASS class A { constructor() {} }; A.toString():::'class A { constructor() {} }' 16 PASS 'use strict'; class A { constructor() {} }; A.toString():::'class A { constructor() {} }' 17 17 PASS class A { constructor() {} }; (new A) instanceof A 18 18 PASS 'use strict'; class A { constructor() {} }; (new A) instanceof A 19 PASS class A { constructor() { this.base = A; } }; (new A).base.toString():::' function A() { this.base = A;}'20 PASS 'use strict'; class A { constructor() { this.base = A; } }; (new A).base.toString():::' function A() { this.base = A;}'19 PASS class A { constructor() { this.base = A; } }; (new A).base.toString():::'class A { constructor() { this.base = A; } }' 20 PASS 'use strict'; class A { constructor() { this.base = A; } }; (new A).base.toString():::'class A { constructor() { this.base = A; } }' 21 21 PASS class A { constructor() {} }; class B extends A {}; 22 22 PASS 'use strict'; class A { constructor() {} }; class B extends A {}; 23 PASS class A { constructor() {} }; class B extends A { constructor() {} }; B.toString():::' function B() {}'24 PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() {} }; B.toString():::' function B() {}'23 PASS class A { constructor() {} }; class B extends A { constructor() {} }; B.toString():::'class B extends A { constructor() {} }' 24 PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() {} }; B.toString():::'class B extends A { constructor() {} }' 25 25 PASS class A { constructor() {} }; class B extends A {}; (new B) instanceof A 26 26 PASS 'use strict'; class A { constructor() {} }; class B extends A {}; (new B) instanceof A 27 27 PASS class A { constructor() {} }; class B extends A {}; (new B) instanceof B 28 28 PASS 'use strict'; class A { constructor() {} }; class B extends A {}; (new B) instanceof B 29 PASS class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString():::' function A() {}'30 PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString():::' function A() {}'31 PASS class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString():::' function B() { super(); this.base = A; this.derived = B;}'32 PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString():::' function B() { super(); this.base = A; this.derived = B;}'29 PASS class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString():::'class A { constructor() {} }' 30 PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString():::'class A { constructor() {} }' 31 PASS class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString():::'class B extends A { constructor() { super(); this.base = A; this.derived = B; } }' 32 PASS 'use strict'; class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString():::'class B extends A { constructor() { super(); this.base = A; this.derived = B; } }' 33 33 34 34 Class expression … … 53 53 PASS (new (class A { constructor() { this.base = A; } })).base 54 54 PASS 'use strict'; (new (class A { constructor() { this.base = A; } })).base 55 PASS (new (class A { constructor() { this.base = A; } })).base.toString():::" function A() { this.base = A;}"56 PASS 'use strict'; (new (class A { constructor() { this.base = A; } })).base.toString():::" function A() { this.base = A;}"55 PASS (new (class A { constructor() { this.base = A; } })).base.toString():::"class A { constructor() { this.base = A; } }" 56 PASS 'use strict'; (new (class A { constructor() { this.base = A; } })).base.toString():::"class A { constructor() { this.base = A; } }" 57 57 PASS class A {}; (class B extends A {}) 58 58 PASS 'use strict'; class A {}; (class B extends A {}) … … 65 65 PASS class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A 66 66 PASS 'use strict'; class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A 67 PASS class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString():::' function A() {}'68 PASS 'use strict'; class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString():::' function A() {}'69 PASS class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString():::' function B() { super(); this.base = A; this.derived = B;}'70 PASS 'use strict'; class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString():::' function B() { super(); this.base = A; this.derived = B;}'67 PASS class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString():::'class A { constructor() {} }' 68 PASS 'use strict'; class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString():::'class A { constructor() {} }' 69 PASS class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString():::'class B extends A { constructor() { super(); this.base = A; this.derived = B; } }' 70 PASS 'use strict'; class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString():::'class B extends A { constructor() { super(); this.base = A; this.derived = B; } }' 71 71 72 72 Class expression assignment to variable … … 75 75 PASS var VarA = class {} 76 76 PASS 'use strict'; var VarA = class {} 77 PASS var VarA = class { constructor() {} }; VarA.toString():::' function () {}'78 PASS 'use strict'; var VarA = class { constructor() {} }; VarA.toString():::' function () {}'77 PASS var VarA = class { constructor() {} }; VarA.toString():::'class { constructor() {} }' 78 PASS 'use strict'; var VarA = class { constructor() {} }; VarA.toString():::'class { constructor() {} }' 79 79 PASS VarA:::ReferenceError: Can't find variable: VarA 80 80 PASS 'use strict'; VarA:::ReferenceError: Can't find variable: VarA 81 81 PASS var VarA = class A { constructor() {} } 82 82 PASS 'use strict'; var VarA = class A { constructor() {} } 83 PASS var VarA = class A { constructor() {} }; VarA.toString():::' function A() {}'84 PASS 'use strict'; var VarA = class A { constructor() {} }; VarA.toString():::' function A() {}'83 PASS var VarA = class A { constructor() {} }; VarA.toString():::'class A { constructor() {} }' 84 PASS 'use strict'; var VarA = class A { constructor() {} }; VarA.toString():::'class A { constructor() {} }' 85 85 PASS var VarA = class A { constructor() {} }; A.toString():::ReferenceError: Can't find variable: A 86 86 PASS 'use strict'; var VarA = class A { constructor() {} }; A.toString():::ReferenceError: Can't find variable: A 87 87 PASS var VarA = class A { constructor() {} }; (new VarA) instanceof VarA 88 88 PASS 'use strict'; var VarA = class A { constructor() {} }; (new VarA) instanceof VarA 89 PASS var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString():::' function A() { this.base = A;}'90 PASS 'use strict'; var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString():::' function A() { this.base = A;}'89 PASS var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString():::'class A { constructor() { this.base = A; } }' 90 PASS 'use strict'; var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString():::'class A { constructor() { this.base = A; } }' 91 91 PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; 92 92 PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; 93 93 PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B:::ReferenceError: Can't find variable: B 94 94 PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B:::ReferenceError: Can't find variable: B 95 PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString():::' function B() {}'96 PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString():::' function B() {}'95 PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString():::'class B extends VarA { constructor() {} }' 96 PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString():::'class B extends VarA { constructor() {} }' 97 97 PASS var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA 98 98 PASS 'use strict'; var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA … … 119 119 PASS eval('var Foo = 10'); Foo:::10 120 120 PASS 'use strict'; eval('var Foo = 10'); Foo:::ReferenceError: Can't find variable: Foo 121 PASS eval('class Bar { constructor() {} }; Bar.toString()');:::' function Bar() {}'121 PASS eval('class Bar { constructor() {} }; Bar.toString()');:::'class Bar { constructor() {} }' 122 122 PASS 'use strict'; eval('class Bar { constructor() {} }'); Bar.toString():::ReferenceError: Can't find variable: Bar 123 123 PASS successfullyParsed -
trunk/LayoutTests/js/function-toString-vs-name.html
r197815 r198042 6 6 <body> 7 7 <script src="script-tests/function-toString-vs-name.js"></script> 8 9 <script> 10 failures = ""; 11 12 section = "global class statements with identical class bodies from different scripts"; 13 </script> 14 <!-- Case 1: A global class statement: --> 15 <script>class globalClass1 { constructor(x) { return x; } stuff() { return 5; } }</script> 16 17 <!-- Case 2: Same class body as Case 1 but indented. --> 18 <script>class globalClass2 { constructor(x) { return x; } stuff() { return 5; } }</script> 19 20 <!-- Case 3: Same class body indented on the same line. --> 21 <script>class globalClass3 { constructor(x) { return x; } stuff() { return 5; } }</script> 22 23 <script> 24 section = "global class expressions with identical class bodies from different scripts"; 25 </script> 26 <!-- Case 1: A global class expression: --> 27 <script>var globalClassExpr1 = class { constructor(x) { return x; } stuff() { return 5; } }</script> 28 29 <!-- Case 2: Same class body as Case 1 but indented. --> 30 <script>var globalClassExpr2 = class { constructor(x) { return x; } stuff() { return 5; } }</script> 31 32 <!-- Case 3: Same class body indented on the same line. --> 33 <script>var globalClassExpr3 = class { constructor(x) { return x; } stuff() { return 5; } }</script> 34 35 <script> 36 test(globalClass1, "globalClass1", "class globalClass1 { constructor(x) { return x; } stuff() { return 5; } }"); 37 test(globalClass2, "globalClass2", "class globalClass2 { constructor(x) { return x; } stuff() { return 5; } }"); 38 test(globalClass3, "globalClass3", "class globalClass3 { constructor(x) { return x; } stuff() { return 5; } }"); 39 40 test(globalClassExpr1, "globalClassExpr1", "class { constructor(x) { return x; } stuff() { return 5; } }"); 41 test(globalClassExpr2, "globalClassExpr2", "class { constructor(x) { return x; } stuff() { return 5; } }"); 42 test(globalClassExpr3, "globalClassExpr3", "class { constructor(x) { return x; } stuff() { return 5; } }"); 43 44 if (failureCount) 45 throw Error("Found " + failureCount + " failures:\n" + failures); 46 </script> 47 8 48 <script src="../resources/js-test-post.js"></script> 9 49 </body> -
trunk/LayoutTests/js/script-tests/class-syntax-name.js
r187680 r198042 69 69 runTestShouldThrow("class { constructor() {} }"); 70 70 runTestShouldNotThrow("class A { constructor() {} }"); 71 runTestShouldBe("class A { constructor() {} }; A.toString()", "' function A() {}'");71 runTestShouldBe("class A { constructor() {} }; A.toString()", "'class A { constructor() {} }'"); 72 72 runTestShouldBeTrue("class A { constructor() {} }; (new A) instanceof A"); 73 runTestShouldBe("class A { constructor() { this.base = A; } }; (new A).base.toString()", "' function A() { this.base = A;}'");73 runTestShouldBe("class A { constructor() { this.base = A; } }; (new A).base.toString()", "'class A { constructor() { this.base = A; } }'"); 74 74 runTestShouldNotThrow("class A { constructor() {} }; class B extends A {};"); 75 runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() {} }; B.toString()", "' function B() {}'");75 runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() {} }; B.toString()", "'class B extends A { constructor() {} }'"); 76 76 runTestShouldBeTrue("class A { constructor() {} }; class B extends A {}; (new B) instanceof A"); 77 77 runTestShouldBeTrue("class A { constructor() {} }; class B extends A {}; (new B) instanceof B"); 78 runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString()", "' function A() {}'");79 runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString()", "' function B() { super(); this.base = A; this.derived = B;}'");78 runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).base.toString()", "'class A { constructor() {} }'"); 79 runTestShouldBe("class A { constructor() {} }; class B extends A { constructor() { super(); this.base = A; this.derived = B; } }; (new B).derived.toString()", "'class B extends A { constructor() { super(); this.base = A; this.derived = B; } }'"); 80 80 81 81 // Class expression. Class name not added to scope. Class name is available inside class scope. … … 91 91 runTestShouldBe("typeof (new (class A {}))", '"object"'); 92 92 runTestShouldNotThrow("(new (class A { constructor() { this.base = A; } })).base"); 93 runTestShouldBe("(new (class A { constructor() { this.base = A; } })).base.toString()", '" function A() { this.base = A;}"');93 runTestShouldBe("(new (class A { constructor() { this.base = A; } })).base.toString()", '"class A { constructor() { this.base = A; } }"'); 94 94 runTestShouldNotThrow("class A {}; (class B extends A {})"); 95 95 runTestShouldThrow("class A {}; (class B extends A {}); B"); … … 97 97 runTestShouldNotThrow("class A {}; new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })"); 98 98 runTestShouldBeTrue("class A {}; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })) instanceof A"); 99 runTestShouldBe("class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString()", "' function A() {}'");100 runTestShouldBe("class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString()", "' function B() { super(); this.base = A; this.derived = B;}'");99 runTestShouldBe("class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).base.toString()", "'class A { constructor() {} }'"); 100 runTestShouldBe("class A { constructor() {} }; (new (class B extends A { constructor() { super(); this.base = A; this.derived = B; } })).derived.toString()", "'class B extends A { constructor() { super(); this.base = A; this.derived = B; } }'"); 101 101 102 102 // Assignment of a class expression to a variable. Variable name available in scope, class name is not. Class name is available inside class scope. … … 104 104 runTestShouldThrow("A"); 105 105 runTestShouldNotThrow("var VarA = class {}"); 106 runTestShouldBe("var VarA = class { constructor() {} }; VarA.toString()", "' function () {}'");106 runTestShouldBe("var VarA = class { constructor() {} }; VarA.toString()", "'class { constructor() {} }'"); 107 107 runTestShouldThrow("VarA"); 108 108 runTestShouldNotThrow("var VarA = class A { constructor() {} }"); 109 runTestShouldBe("var VarA = class A { constructor() {} }; VarA.toString()", "' function A() {}'");109 runTestShouldBe("var VarA = class A { constructor() {} }; VarA.toString()", "'class A { constructor() {} }'"); 110 110 runTestShouldThrow("var VarA = class A { constructor() {} }; A.toString()"); 111 111 runTestShouldBeTrue("var VarA = class A { constructor() {} }; (new VarA) instanceof VarA"); 112 runTestShouldBe("var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString()", "' function A() { this.base = A;}'");112 runTestShouldBe("var VarA = class A { constructor() { this.base = A; } }; (new VarA).base.toString()", "'class A { constructor() { this.base = A; } }'"); 113 113 runTestShouldNotThrow("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} };"); 114 114 runTestShouldThrow("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; B"); 115 runTestShouldBe("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString()", "' function B() {}'");115 runTestShouldBe("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { constructor() {} }; VarB.toString()", "'class B extends VarA { constructor() {} }'"); 116 116 runTestShouldBeTrue("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarA"); 117 117 runTestShouldBeTrue("var VarA = class A { constructor() {} }; var VarB = class B extends VarA { }; (new VarB) instanceof VarB"); … … 129 129 shouldBe("eval('var Foo = 10'); Foo", "10"); 130 130 shouldThrow("'use strict'; eval('var Foo = 10'); Foo"); 131 shouldBe("eval('class Bar { constructor() {} }; Bar.toString()');", "' function Bar() {}'");131 shouldBe("eval('class Bar { constructor() {} }; Bar.toString()');", "'class Bar { constructor() {} }'"); 132 132 shouldThrow("'use strict'; eval('class Bar { constructor() {} }'); Bar.toString()"); -
trunk/LayoutTests/js/script-tests/function-toString-vs-name.js
r197867 r198042 219 219 } 220 220 221 section = "class from statement"; 222 (function () { 223 class foo {} 224 class bar {} 225 class bax { static name() {} } 226 let baz = bar; 227 class goo extends foo {} 228 229 test(foo, "foo", "class foo {}"); 230 test(bar, "bar", "class bar {}"); 231 shouldBe("typeof bax.name of ", "bax", typeof bax.name, "function"); 232 shouldBe("toString of ", "bax", bax.toString(), "class bax { static name() {} }"); 233 test(baz, "bar", "class bar {}"); 234 test(goo, "goo", "class goo extends foo {}"); 235 236 section = "bound class from statement"; 237 { 238 let bound1 = foo.bind({}); 239 test(bound1, "bound foo", "function foo() { [native code] }"); 240 let bound2 = bar.bind({}); 241 test(bound2, "bound bar", "function bar() { [native code] }"); 242 let bound3 = bax.bind({}); 243 test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string. 244 let bound4 = baz.bind({}); 245 test(bound4, "bound bar", "function bar() { [native code] }"); 246 let bound5 = goo.bind({}); 247 test(bound5, "bound goo", "function goo() { [native code] }"); 248 } 249 })(); 250 251 section = "class with constructor from statement"; 252 (function () { 253 class foo { constructor(x) {} } 254 class bar { constructor() {} } 255 class bax { static name() {} constructor() {} } 256 let baz = bar; 257 class goo extends foo { constructor() { super(5); } } 258 259 test(foo, "foo", "class foo { constructor(x) {} }"); 260 test(bar, "bar", "class bar { constructor() {} }"); 261 shouldBe("typeof bax.name of ", "bax", typeof bax.name, "function"); 262 shouldBe("toString of ", "bax", bax.toString(), "class bax { static name() {} constructor() {} }"); 263 test(baz, "bar", "class bar { constructor() {} }"); 264 test(goo, "goo", "class goo extends foo { constructor() { super(5); } }"); 265 266 section = "bound class with constructor from statement"; 267 { 268 let bound1 = foo.bind({}); 269 test(bound1, "bound foo", "function foo() { [native code] }"); 270 let bound2 = bar.bind({}); 271 test(bound2, "bound bar", "function bar() { [native code] }"); 272 let bound3 = bax.bind({}); 273 test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string. 274 let bound4 = baz.bind({}); 275 test(bound4, "bound bar", "function bar() { [native code] }"); 276 let bound5 = goo.bind({}); 277 test(bound5, "bound goo", "function goo() { [native code] }"); 278 } 279 })(); 280 281 section = "class from expression"; 282 (function () { 283 let foo = class namedFoo {} 284 let bar = class {} 285 let bax = class { static name() {} } 286 let baz = bar; 287 let goo = class extends foo {} 288 289 test(foo, "namedFoo", "class namedFoo {}"); 290 test(bar, "bar", "class {}"); 291 shouldBe("typeof bax.name of ", "bax", typeof bax.name, "function"); 292 shouldBe("toString of ", "bax", bax.toString(), "class { static name() {} }"); 293 test(baz, "bar", "class {}"); 294 test(goo, "goo", "class extends foo {}"); 295 296 section = "bound class from expression"; 297 { 298 let bound1 = foo.bind({}); 299 test(bound1, "bound namedFoo", "function namedFoo() { [native code] }"); 300 let bound2 = bar.bind({}); 301 test(bound2, "bound bar", "function bar() { [native code] }"); 302 let bound3 = bax.bind({}); 303 test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string. 304 let bound4 = baz.bind({}); 305 test(bound4, "bound bar", "function bar() { [native code] }"); 306 let bound5 = goo.bind({}); 307 test(bound5, "bound goo", "function goo() { [native code] }"); 308 } 309 })(); 310 311 section = "class with constructor from expression"; 312 (function () { 313 let foo = class namedFoo { constructor(x) {} } 314 let bar = class { constructor() {} } 315 let bax = class { static name() {} constructor() {} } 316 let baz = bar; 317 let goo = class extends foo { constructor() { super(x) } } 318 319 test(foo, "namedFoo", "class namedFoo { constructor(x) {} }"); 320 test(bar, "bar", "class { constructor() {} }"); 321 shouldBe("typeof bax.name of ", "bax", typeof bax.name, "function"); 322 shouldBe("toString of ", "bax", bax.toString(), "class { static name() {} constructor() {} }"); 323 test(baz, "bar", "class { constructor() {} }"); 324 test(goo, "goo", "class extends foo { constructor() { super(x) } }"); 325 326 section = "bound class with constructor from expression"; 327 { 328 let bound1 = foo.bind({}); 329 test(bound1, "bound namedFoo", "function namedFoo() { [native code] }"); 330 let bound2 = bar.bind({}); 331 test(bound2, "bound bar", "function bar() { [native code] }"); 332 let bound3 = bax.bind({}); 333 test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string. 334 let bound4 = baz.bind({}); 335 test(bound4, "bound bar", "function bar() { [native code] }"); 336 let bound5 = goo.bind({}); 337 test(bound5, "bound goo", "function goo() { [native code] }"); 338 } 339 })(); 340 341 section = "class in object property"; 342 (function () { 343 class gooBase {} 344 let o = { 345 foo: class {}, 346 bar: class {}, 347 bax: class { static name() {} }, 348 goo: class extends gooBase {}, 349 }; 350 o.bay = o.bar; 351 o.baz = class {}; 352 353 test(o.foo, "foo", "class {}"); 354 test(o.bar, "bar", "class {}"); 355 shouldBe("typeof o.bax.name of ", "o.bax", typeof o.bax.name, "function"); 356 shouldBe("toString of ", "o.bax", o.bax.toString(), "class { static name() {} }"); 357 test(o.bay, "bar", "class {}"); 358 test(o.baz, "", "class {}"); 359 test(o.goo, "goo", "class extends gooBase {}"); 360 361 section = "bound class in object property"; 362 { 363 let bound1 = o.foo.bind({}); 364 test(bound1, "bound foo", "function foo() { [native code] }"); 365 let bound2 = o.bar.bind({}); 366 test(bound2, "bound bar", "function bar() { [native code] }"); 367 let bound3 = o.bax.bind({}); 368 test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string. 369 let bound4 = o.bay.bind({}); 370 test(bound4, "bound bar", "function bar() { [native code] }"); 371 let bound5 = o.baz.bind({}); 372 test(bound5, "bound ", "function() { [native code] }"); 373 let bound6 = o.goo.bind({}); 374 test(bound6, "bound goo", "function goo() { [native code] }"); 375 } 376 })(); 377 378 section = "class with constructor in object property"; 379 (function () { 380 class gooBase { constructor(x) {} } 381 let o = { 382 foo: class { constructor(x) {} }, 383 bar: class { constructor() {} }, 384 bax: class { static name() {} constructor() {} }, 385 goo: class extends gooBase { constructor() { super(5); } }, 386 }; 387 o.bay = o.bar; 388 o.baz = class { constructor() {} }; 389 390 test(o.foo, "foo", "class { constructor(x) {} }"); 391 test(o.bar, "bar", "class { constructor() {} }"); 392 shouldBe("typeof o.bax.name of ", "o.bax", typeof o.bax.name, "function"); 393 shouldBe("toString of ", "o.bax", o.bax.toString(), "class { static name() {} constructor() {} }"); 394 test(o.bay, "bar", "class { constructor() {} }"); 395 test(o.baz, "", "class { constructor() {} }"); 396 test(o.goo, "goo", "class extends gooBase { constructor() { super(5); } }"); 397 398 section = "bound class with constructor in object property"; 399 { 400 let bound1 = o.foo.bind({}); 401 test(bound1, "bound foo", "function foo() { [native code] }"); 402 let bound2 = o.bar.bind({}); 403 test(bound2, "bound bar", "function bar() { [native code] }"); 404 let bound3 = o.bax.bind({}); 405 test(bound3, "bound ", "function() { [native code] }"); // bax.name is not a string. 406 let bound4 = o.bay.bind({}); 407 test(bound4, "bound bar", "function bar() { [native code] }"); 408 let bound5 = o.baz.bind({}); 409 test(bound5, "bound ", "function() { [native code] }"); 410 let bound6 = o.goo.bind({}); 411 test(bound6, "bound goo", "function goo() { [native code] }"); 412 } 413 })(); 414 415 section = "global class statement"; 416 // Checking if there are CodeCache badness that can result from global class statements 417 // with identical bodies. 418 class globalCS1 { constructor(x) { return x; } stuff() { return 5; } } 419 // Identical class body as CS1. 420 class globalCS2 { constructor(x) { return x; } stuff() { return 5; } } 421 // Identical constructor as CS2 & CS1, but different otherwise. 422 class globalCS3 { constructor(x) { return x; } stuff3() { return 15; } } 423 424 test(globalCS1, "globalCS1", "class globalCS1 { constructor(x) { return x; } stuff() { return 5; } }"); 425 test(globalCS2, "globalCS2", "class globalCS2 { constructor(x) { return x; } stuff() { return 5; } }"); 426 test(globalCS3, "globalCS3", "class globalCS3 { constructor(x) { return x; } stuff3() { return 15; } }"); 427 428 section = "global class expression"; 429 // Checking if there are CodeCache badness that can result from global class expressions 430 // with identical bodies. 431 var globalCE1 = class { constructor(x) { return x; } stuff() { return 5; } } 432 // Identical class body as CSE1. 433 var globalCE2 = class { constructor(x) { return x; } stuff() { return 5; } } 434 // Identical constructor as CSE2 & CSE1, but different otherwise. 435 var globalCE3 = class { constructor(x) { return x; } stuff3() { return 15; } } 436 437 test(globalCE1, "globalCE1", "class { constructor(x) { return x; } stuff() { return 5; } }"); 438 test(globalCE2, "globalCE2", "class { constructor(x) { return x; } stuff() { return 5; } }"); 439 test(globalCE3, "globalCE3", "class { constructor(x) { return x; } stuff3() { return 15; } }"); 440 441 section = "class statements in eval"; 442 // Checking if there are CodeCache badness that can result from class statements in 443 // identical eval statements. 444 (function () { 445 let body1 = "class foo { constructor(x) { return x; } stuff() { return 5; } }"; 446 // Identical class body as body1. 447 let body2 = "class foo { constructor(x) { return x; } stuff() { return 5; } }"; 448 // Identical constructor as body1 & body2, but different otherwise. 449 let body3 = "class foo3 { constructor(x) { return x; } stuff3() { return 15; } }"; 450 451 let bar1 = eval(body1); 452 let bar2 = eval(body2); 453 let bar3 = eval(body3); 454 let bar4 = eval(body1); 455 456 test(bar1, "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }"); 457 test(bar2, "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }"); 458 test(bar3, "foo3", "class foo3 { constructor(x) { return x; } stuff3() { return 15; } }"); 459 test(bar4, "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }"); 460 })(); 461 462 section = "class expressions in eval"; 463 // Checking if there are CodeCache badness that can result from class expressions in 464 // identical eval statements. 465 (function () { 466 let body1 = "var foo = class { constructor(x) { return x; } stuff() { return 5; } }; foo"; 467 // Identical class body as body1. 468 let body2 = "var foo = class { constructor(x) { return x; } stuff() { return 5; } }; foo"; 469 // Identical constructor as body1 & body2, but different otherwise. 470 let body3 = "var foo3 = class { constructor(x) { return x; } stuff3() { return 15; } }; foo3"; 471 472 let bar1 = eval(body1); 473 let bar2 = eval(body2); 474 let bar3 = eval(body3); 475 let bar4 = eval(body1); 476 477 test(bar1, "foo", "class { constructor(x) { return x; } stuff() { return 5; } }"); 478 test(bar2, "foo", "class { constructor(x) { return x; } stuff() { return 5; } }"); 479 test(bar3, "foo3", "class { constructor(x) { return x; } stuff3() { return 15; } }"); 480 test(bar4, "foo", "class { constructor(x) { return x; } stuff() { return 5; } }"); 481 })(); 482 483 section = "class statements in dynamically created Functions"; 484 // Checking if there are CodeCache badness that can result from dynamically created 485 // Function objects with class statements in identical bodies. 486 (function () { 487 let body1 = "class foo { constructor(x) { return x; } stuff() { return 5; } } return foo;"; 488 // Identical class body as body1. 489 let body2 = "class foo { constructor(x) { return x; } stuff() { return 5; } } return foo;"; 490 // Identical constructor as body1 & body2, but different otherwise. 491 let body3 = "class foo3 { constructor(x) { return x; } stuff3() { return 15; } } return foo3;"; 492 493 let bar1 = new Function(body1); 494 let bar2 = new Function(body2); 495 let bar3 = new Function(body3); 496 497 test(bar1(), "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }"); 498 test(bar2(), "foo", "class foo { constructor(x) { return x; } stuff() { return 5; } }"); 499 test(bar3(), "foo3", "class foo3 { constructor(x) { return x; } stuff3() { return 15; } }"); 500 })(); 501 502 section = "class expressions in dynamically created Functions"; 503 // Checking if there are CodeCache badness that can result from dynamically created 504 // Function objects with class expressions in identical bodies. 505 (function () { 506 let body1 = "var foo = class { constructor(x) { return x; } stuff() { return 5; } }; return foo;"; 507 // Identical class body as body1. 508 let body2 = "var foo = class { constructor(x) { return x; } stuff() { return 5; } }; return foo;"; 509 // Identical constructor as body1 & body2, but different otherwise. 510 let body3 = "var foo3 = class { constructor(x) { return x; } stuff3() { return 15; } }; return foo3;"; 511 512 let bar1 = new Function(body1); 513 let bar2 = new Function(body2); 514 let bar3 = new Function(body3); 515 516 test(bar1(), "foo", "class { constructor(x) { return x; } stuff() { return 5; } }"); 517 test(bar2(), "foo", "class { constructor(x) { return x; } stuff() { return 5; } }"); 518 test(bar3(), "foo3", "class { constructor(x) { return x; } stuff3() { return 15; } }"); 519 })(); 520 221 521 // FIXME: Uncomment these when we've added support for Function.name of computed properties. 222 522 // section = "Object computed string property"; -
trunk/LayoutTests/platform/mac/inspector/model/remote-object-expected.txt
r197966 r198042 4749 4749 "_description": "Person" 4750 4750 }, 4751 "_functionDescription": " function Person(name){}"4751 "_functionDescription": "class Person { constructor(name){} get fullName(){} methodName(p1, p2){} }" 4752 4752 } 4753 4753 … … 4772 4772 "_description": "B" 4773 4773 }, 4774 "_functionDescription": " function B() { super(...arguments);}"4774 "_functionDescription": "class B extends Alpha { methodB(){} }" 4775 4775 } 4776 4776 -
trunk/Source/JavaScriptCore/ChangeLog
r198024 r198042 1 2016-03-11 Mark Lam <mark.lam@apple.com> 2 3 Implement Function.name and Function#toString for ES6 class. 4 https://bugs.webkit.org/show_bug.cgi?id=155336 5 6 Reviewed by Geoffrey Garen. 7 8 The only thing that the ES6 spec says about toString with regards to class 9 objects is: 10 11 "The string representation must have the syntax of a FunctionDeclaration, 12 FunctionExpression, GeneratorDeclaration, GeneratorExpression, ClassDeclaration, 13 ClassExpression, ArrowFunction, MethodDefinition, or GeneratorMethod depending 14 upon the actual characteristics of the object." 15 16 Previously, invoking toString() on a class object will return the function 17 source string of the class' constructor function. This does not conform to the 18 spec in that the toString string for a class does not have the syntax of a 19 ClassDeclaration or ClassExpression. 20 21 This is now fixed by doing the following: 22 23 1. Added "m_classSource" to FunctionExecutable (and correspondingly to 24 UnlinkedFunctionExecutable, FunctionMetadataNode, and ClassExprNode). 25 m_classSource is the SourceCode for the code range "class ... { ... }". 26 27 Since the class constructor function is the in memory representation of the 28 class object, only class constructor functions will have its m_classSource 29 set. m_classSource will be "null" (by default) for all other functions. 30 This is how we know if a FunctionExecutable is for a class. 31 32 Note: FunctionExecutable does not have its own m_classSource. It always gets 33 it from its UnlinkedFunctionExecutable. This is ok to do because our CodeCache 34 currently does not cache UnlinkedFunctionExecutables for class constructors. 35 36 2. The ClassExprNode now tracks the SourceCode range for the class expression. 37 This is used to set m_classSource in the UnlinkedFunctionExecutable at 38 bytecode generation time, and the FunctionExecutable later at bytecode 39 linking time. 40 41 3. Function.prototype.toString() now checks if the function is for a class. 42 If so, it returns the string for the class source instead of just the 43 function source for the class constructor. 44 45 Note: the class source is static from the time the class was parsed. This 46 can introduces some weirdness at runtime. Consider the following: 47 48 var v1 = class {} 49 v1.toString(); // yields "class {}". 50 51 class c2 extends v1 {} 52 53 c2.__proto__ === v1; // yields true i.e. c2 extends v1. 54 c2.toString(); // yields "class c2 extends v1 {}" which is fine. 55 56 v1 = {}; // point v1 to something else now. 57 58 c2.__proto__ === v1; // now yields false i.e. c2 no longer extends v1. 59 // c2 actually extends the class that v1 used to 60 // point to, but ... 61 c2.toString(); // still yields "class c2 extends v1 {}" which is no longer true. 62 63 It is unclear how we can best implement toString() to avoid this issue. 64 The above behavior is how Chrome (Version 51.0.2671.0 canary (64-bit)) 65 currently implements toString() of a class, and we do the same in this patch. 66 In Firefox (45.0), toString() of a class will yield the function source of it 67 constructor function, which is not better. 68 69 In this patch, we also added ES6 compliance for Function.name on class objects: 70 71 4. The ClassExprNode now has a m_ecmaName string for tracking the inferred 72 name of a class according to the ES6 spec. The ASTBuilder now mirrors its 73 handling of FuncExprNodes to ClassExprNodes in setting the nodes' m_ecmaName 74 where relevant. 75 76 The m_ecmaName is later used to set the m_ecmaName of the FunctionExecutable 77 of the class constructor, which in turn is used to populate the initial value 78 of the Function.name property. 79 80 5. Also renamed some variable names (/m_metadata/metadata/) to be consistent with 81 webkit naming convention. 82 83 * bytecode/UnlinkedFunctionExecutable.cpp: 84 (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable): 85 * bytecode/UnlinkedFunctionExecutable.h: 86 * bytecompiler/BytecodeGenerator.cpp: 87 (JSC::BytecodeGenerator::emitNewArrowFunctionExpression): 88 (JSC::BytecodeGenerator::emitNewDefaultConstructor): 89 * bytecompiler/BytecodeGenerator.h: 90 * bytecompiler/NodesCodegen.cpp: 91 (JSC::ClassExprNode::emitBytecode): 92 * parser/ASTBuilder.h: 93 (JSC::ASTBuilder::createAssignResolve): 94 (JSC::ASTBuilder::createYield): 95 (JSC::ASTBuilder::createClassExpr): 96 (JSC::ASTBuilder::createFunctionExpr): 97 (JSC::ASTBuilder::createProperty): 98 (JSC::ASTBuilder::makeAssignNode): 99 * parser/NodeConstructors.h: 100 (JSC::FunctionParameters::FunctionParameters): 101 (JSC::BaseFuncExprNode::BaseFuncExprNode): 102 (JSC::FuncExprNode::FuncExprNode): 103 (JSC::FuncDeclNode::FuncDeclNode): 104 (JSC::ArrowFuncExprNode::ArrowFuncExprNode): 105 (JSC::ClassDeclNode::ClassDeclNode): 106 (JSC::ClassExprNode::ClassExprNode): 107 * parser/Nodes.h: 108 (JSC::ExpressionNode::isDestructuringNode): 109 (JSC::ExpressionNode::isFuncExprNode): 110 (JSC::ExpressionNode::isArrowFuncExprNode): 111 (JSC::ExpressionNode::isClassExprNode): 112 (JSC::ExpressionNode::isCommaNode): 113 (JSC::ExpressionNode::isSimpleArray): 114 (JSC::ExpressionNode::isAdd): 115 * parser/Parser.cpp: 116 (JSC::stringForFunctionMode): 117 (JSC::Parser<LexerType>::parseFunctionInfo): 118 (JSC::Parser<LexerType>::parseClass): 119 * parser/ParserFunctionInfo.h: 120 * parser/SyntaxChecker.h: 121 (JSC::SyntaxChecker::createEmptyLetExpression): 122 (JSC::SyntaxChecker::createYield): 123 (JSC::SyntaxChecker::createClassExpr): 124 (JSC::SyntaxChecker::createFunctionExpr): 125 (JSC::SyntaxChecker::createFunctionMetadata): 126 (JSC::SyntaxChecker::createArrowFunctionExpr): 127 * runtime/Executable.cpp: 128 (JSC::FunctionExecutable::FunctionExecutable): 129 (JSC::FunctionExecutable::finishCreation): 130 * runtime/Executable.h: 131 * runtime/FunctionPrototype.cpp: 132 (JSC::functionProtoFuncToString): 133 * tests/es6.yaml: 134 1 135 2016-03-11 Commit Queue <commit-queue@webkit.org> 2 136 … … 580 714 (catch): Deleted. 581 715 582 >>>>>>> .r197960583 716 2016-03-08 Skachkov Oleksandr <gskachkov@gmail.com> 584 717 -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp
r197867 r198042 1 1 /* 2 * Copyright (C) 2012 , 2013, 2015Apple Inc. All Rights Reserved.2 * Copyright (C) 2012-2013, 2015-2016 Apple Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 106 106 , m_inferredName(node->inferredName()) 107 107 , m_sourceOverride(WTFMove(sourceOverride)) 108 , m_classSource(node->classSource()) 108 109 { 109 110 ASSERT(m_constructorKind == static_cast<unsigned>(node->constructorKind())); -
trunk/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h
r197867 r198042 1 1 /* 2 * Copyright (C) 2012-201 5Apple Inc. All Rights Reserved.2 * Copyright (C) 2012-2016 Apple Inc. All Rights Reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 77 77 const Identifier& name() const { return m_name; } 78 78 const Identifier& ecmaName() const { return m_ecmaName; } 79 void setEcmaName(const Identifier& name) { m_ecmaName = name; } 79 80 const Identifier& inferredName() const { return m_inferredName; } 80 81 unsigned parameterCount() const { return m_parameterCount; }; 81 82 SourceParseMode parseMode() const { return static_cast<SourceParseMode>(m_sourceParseMode); }; 83 84 const SourceCode& classSource() const { return m_classSource; }; 85 void setClassSource(const SourceCode& source) { m_classSource = source; }; 86 82 87 bool isInStrictContext() const { return m_isInStrictContext; } 83 88 FunctionMode functionMode() const { return static_cast<FunctionMode>(m_functionMode); } … … 164 169 Identifier m_inferredName; 165 170 RefPtr<SourceProvider> m_sourceOverride; 171 SourceCode m_classSource; 166 172 167 173 VariableEnvironment m_parentScopeTDZVariables; -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
r197928 r198042 1 1 /* 2 * Copyright (C) 2008 , 2009, 2012-2015Apple Inc. All rights reserved.2 * Copyright (C) 2008-2009, 2012-2016 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> 4 4 * Copyright (C) 2012 Igalia, S.L. … … 2811 2811 } 2812 2812 2813 RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name) 2813 RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name, 2814 const Identifier& ecmaName, const SourceCode& classSource) 2814 2815 { 2815 2816 UnlinkedFunctionExecutable* executable = m_vm->builtinExecutables()->createDefaultConstructor(constructorKind, name); 2816 2817 executable->setInvalidTypeProfilingOffsets(); 2818 executable->setEcmaName(ecmaName); 2819 executable->setClassSource(classSource); 2817 2820 2818 2821 unsigned index = m_codeBlock->addFunctionExpr(executable); -
trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
r197928 r198042 1 1 /* 2 * Copyright (C) 2008 , 2009, 2012-2015Apple Inc. All rights reserved.2 * Copyright (C) 2008-2009, 2012-2016 Apple Inc. All rights reserved. 3 3 * Copyright (C) 2008 Cameron Zwarich <cwzwarich@uwaterloo.ca> 4 4 * Copyright (C) 2012 Igalia, S.L. … … 519 519 RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*); 520 520 RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode* func); 521 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name );521 RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource); 522 522 RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*); 523 523 RegisterID* emitNewRegExp(RegisterID* dst, RegExp*); -
trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
r197410 r198042 2 2 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003 , 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013, 2015Apple Inc. All rights reserved.4 * Copyright (C) 2003-2009, 2012-2013, 2015-2016 Apple Inc. All rights reserved. 5 5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) 6 6 * Copyright (C) 2007 Maks Orlovich … … 3221 3221 3222 3222 // FIXME: Make the prototype non-configurable & non-writable. 3223 if (m_constructorExpression) 3223 if (m_constructorExpression) { 3224 ASSERT(m_constructorExpression->isFuncExprNode()); 3225 FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata(); 3226 metadata->setEcmaName(ecmaName()); 3227 metadata->setClassSource(m_classSource); 3224 3228 constructor = generator.emitNode(dst, m_constructorExpression); 3225 else {3229 } else { 3226 3230 constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst), 3227 m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base, m_name); 3231 m_classHeritage ? ConstructorKind::Derived : ConstructorKind::Base, 3232 m_name, ecmaName(), m_classSource); 3228 3233 } 3229 3234 -
trunk/Source/JavaScriptCore/parser/ASTBuilder.h
r197947 r198042 1 1 /* 2 * Copyright (C) 2010, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2010, 2013, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 347 347 metadata->setEcmaName(ident); 348 348 metadata->setInferredName(ident); 349 } 349 } else if (rhs->isClassExprNode()) 350 static_cast<ClassExprNode*>(rhs)->setEcmaName(ident); 350 351 AssignResolveNode* node = new (m_parserArena) AssignResolveNode(location, ident, rhs, assignmentContext); 351 352 setExceptionLocation(node, start, divot, end); … … 365 366 } 366 367 367 ClassExprNode* createClassExpr(const JSTokenLocation& location, const Identifier& name, VariableEnvironment& classEnvironment, ExpressionNode* constructor,368 ClassExprNode* createClassExpr(const JSTokenLocation& location, const ParserClassInfo<ASTBuilder>& classInfo, VariableEnvironment& classEnvironment, ExpressionNode* constructor, 368 369 ExpressionNode* parentClass, PropertyListNode* instanceMethods, PropertyListNode* staticMethods) 369 370 { 370 return new (m_parserArena) ClassExprNode(location, name, classEnvironment, constructor, parentClass, instanceMethods, staticMethods); 371 SourceCode source = m_sourceCode->subExpression(classInfo.startOffset, classInfo.endOffset, classInfo.startLine, classInfo.startColumn); 372 return new (m_parserArena) ClassExprNode(location, *classInfo.className, source, classEnvironment, constructor, parentClass, instanceMethods, staticMethods); 371 373 } 372 374 … … 443 445 metadata->setEcmaName(*propertyName); 444 446 metadata->setInferredName(*propertyName); 445 } 447 } else if (node->isClassExprNode()) 448 static_cast<ClassExprNode*>(node)->setEcmaName(*propertyName); 446 449 return new (m_parserArena) PropertyNode(*propertyName, node, type, putType, superBinding); 447 450 } … … 1302 1305 metadata->setEcmaName(resolve->identifier()); 1303 1306 metadata->setInferredName(resolve->identifier()); 1304 } 1307 } else if (expr->isClassExprNode()) 1308 static_cast<ClassExprNode*>(expr)->setEcmaName(resolve->identifier()); 1305 1309 AssignResolveNode* node = new (m_parserArena) AssignResolveNode(location, resolve->identifier(), expr, AssignmentContext::AssignmentExpression); 1306 1310 setExceptionLocation(node, start, divot, end); -
trunk/Source/JavaScriptCore/parser/NodeConstructors.h
r197915 r198042 1 1 /* 2 * Copyright (C) 2009, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2009, 2013, 2015 Apple Inc. All rights reserved. 3 3 * 4 4 * This library is free software; you can redistribute it and/or … … 891 891 892 892 893 inline BaseFuncExprNode::BaseFuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* m _metadata, const SourceCode& source)894 : ExpressionNode(location) 895 , m_metadata(m _metadata)893 inline BaseFuncExprNode::BaseFuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source) 894 : ExpressionNode(location) 895 , m_metadata(metadata) 896 896 { 897 897 m_metadata->finishParsing(source, ident, FunctionExpression); 898 898 } 899 899 900 inline FuncExprNode::FuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* m _metadata, const SourceCode& source)901 : BaseFuncExprNode(location, ident, m _metadata, source)902 { 903 } 904 905 inline FuncDeclNode::FuncDeclNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* m _metadata, const SourceCode& source)906 : StatementNode(location) 907 , m_metadata(m _metadata)900 inline FuncExprNode::FuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source) 901 : BaseFuncExprNode(location, ident, metadata, source) 902 { 903 } 904 905 inline FuncDeclNode::FuncDeclNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source) 906 : StatementNode(location) 907 , m_metadata(metadata) 908 908 { 909 909 m_metadata->finishParsing(source, ident, FunctionDeclaration); 910 910 } 911 911 912 inline ArrowFuncExprNode::ArrowFuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* m _metadata, const SourceCode& source)913 : BaseFuncExprNode(location, ident, m _metadata, source)912 inline ArrowFuncExprNode::ArrowFuncExprNode(const JSTokenLocation& location, const Identifier& ident, FunctionMetadataNode* metadata, const SourceCode& source) 913 : BaseFuncExprNode(location, ident, metadata, source) 914 914 { 915 915 } … … 928 928 } 929 929 930 inline ClassExprNode::ClassExprNode(const JSTokenLocation& location, const Identifier& name, VariableEnvironment& classEnvironment, ExpressionNode* constructorExpression, ExpressionNode* classHeritage, PropertyListNode* instanceMethods, PropertyListNode* staticMethods)930 inline ClassExprNode::ClassExprNode(const JSTokenLocation& location, const Identifier& name, const SourceCode& classSource, VariableEnvironment& classEnvironment, ExpressionNode* constructorExpression, ExpressionNode* classHeritage, PropertyListNode* instanceMethods, PropertyListNode* staticMethods) 931 931 : ExpressionNode(location) 932 932 , VariableEnvironmentNode(classEnvironment) 933 , m_classSource(classSource) 933 934 , m_name(name) 935 , m_ecmaName(&name) 934 936 , m_constructorExpression(constructorExpression) 935 937 , m_classHeritage(classHeritage) -
trunk/Source/JavaScriptCore/parser/Nodes.h
r197928 r198042 2 2 * Copyright (C) 1999-2000 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003 , 2004, 2005, 2006, 2007, 2008, 2009, 2013, 2015Apple Inc. All rights reserved.4 * Copyright (C) 2003-2009, 2013, 2015-2016 Apple Inc. All rights reserved. 5 5 * Copyright (C) 2007 Cameron Zwarich (cwzwarich@uwaterloo.ca) 6 6 * Copyright (C) 2007 Maks Orlovich … … 167 167 virtual bool isFuncExprNode() const { return false; } 168 168 virtual bool isArrowFuncExprNode() const { return false; } 169 virtual bool isClassExprNode() const { return false; } 169 170 virtual bool isCommaNode() const { return false; } 170 171 virtual bool isSimpleArray() const { return false; } … … 1845 1846 void overrideName(const Identifier& ident) { m_ident = ident; } 1846 1847 const Identifier& ident() { return m_ident; } 1847 void setEcmaName(const Identifier& ecmaName) { ASSERT(!ecmaName.isNull());m_ecmaName = ecmaName; }1848 void setEcmaName(const Identifier& ecmaName) { m_ecmaName = ecmaName; } 1848 1849 const Identifier& ecmaName() { return m_ident.isEmpty() ? m_ecmaName : m_ident; } 1849 1850 void setInferredName(const Identifier& inferredName) { ASSERT(!inferredName.isNull()); m_inferredName = inferredName; } … … 1863 1864 1864 1865 const SourceCode& source() const { return m_source; } 1866 const SourceCode& classSource() const { return m_classSource; } 1867 void setClassSource(const SourceCode& source) { m_classSource = source; } 1865 1868 1866 1869 int startStartOffset() const { return m_startStartOffset; } … … 1889 1892 int m_parametersStart; 1890 1893 SourceCode m_source; 1894 SourceCode m_classSource; 1891 1895 int m_startStartOffset; 1892 1896 unsigned m_parameterCount; … … 1975 1979 using ParserArenaDeletable::operator new; 1976 1980 1977 ClassExprNode(const JSTokenLocation&, const Identifier&, VariableEnvironment& classEnvironment, ExpressionNode* constructorExpresssion, 1981 ClassExprNode(const JSTokenLocation&, const Identifier&, const SourceCode& classSource, 1982 VariableEnvironment& classEnvironment, ExpressionNode* constructorExpresssion, 1978 1983 ExpressionNode* parentClass, PropertyListNode* instanceMethods, PropertyListNode* staticMethods); 1979 1984 1980 1985 const Identifier& name() { return m_name; } 1981 1982 private: 1983 RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; 1984 1986 const Identifier& ecmaName() { return m_ecmaName ? *m_ecmaName : m_name; } 1987 void setEcmaName(const Identifier& name) { m_ecmaName = m_name.isNull() ? &name : &m_name; } 1988 1989 private: 1990 RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override; 1991 1992 bool isClassExprNode() const override { return true; } 1993 1994 SourceCode m_classSource; 1985 1995 const Identifier& m_name; 1996 const Identifier* m_ecmaName; 1986 1997 ExpressionNode* m_constructorExpression; 1987 1998 ExpressionNode* m_classHeritage; -
trunk/Source/JavaScriptCore/parser/Parser.cpp
r197947 r198042 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 3 * Copyright (C) 2001 Peter Kelly (pmk@post.com) 4 * Copyright (C) 2003, 2006 , 2007, 2008, 2009, 2010, 2013Apple Inc. All rights reserved.4 * Copyright (C) 2003, 2006-2010, 2013, 2016 Apple Inc. All rights reserved. 5 5 * 6 6 * This library is free software; you can redistribute it and/or … … 2194 2194 ASSERT(match(CLASSTOKEN)); 2195 2195 JSTokenLocation location(tokenLocation()); 2196 info.startLine = location.line; 2197 info.startColumn = tokenColumn(); 2198 info.startOffset = location.startOffset; 2196 2199 next(); 2197 2200 … … 2204 2207 if (match(IDENT)) { 2205 2208 className = m_token.m_data.ident; 2206 info.className = className;2207 2209 next(); 2208 2210 failIfTrue(classScope->declareLexicalVariable(className, true) & DeclarationResult::InvalidStrictMode, "'", className->impl(), "' is not a valid class name"); … … 2215 2217 className = &m_vm->propertyNames->nullIdentifier; 2216 2218 ASSERT(className); 2219 info.className = className; 2217 2220 2218 2221 TreeExpression parentClass = 0; … … 2344 2347 } 2345 2348 2349 info.endOffset = tokenLocation().endOffset - 1; 2346 2350 consumeOrFail(CLOSEBRACE, "Expected a closing '}' after a class body"); 2347 2351 2348 auto classExpression = context.createClassExpr(location, *className, classScope->finalizeLexicalEnvironment(), constructor, parentClass, instanceMethods, staticMethods);2352 auto classExpression = context.createClassExpr(location, info, classScope->finalizeLexicalEnvironment(), constructor, parentClass, instanceMethods, staticMethods); 2349 2353 popScope(classScope, TreeBuilder::NeedsFreeVariableInfo); 2350 2354 return classExpression; -
trunk/Source/JavaScriptCore/parser/ParserFunctionInfo.h
r192147 r198042 1 1 /* 2 * Copyright (C) 2015 Apple Inc. All rights reserved.2 * Copyright (C) 2015-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 44 44 template <class TreeBuilder> 45 45 struct ParserClassInfo { 46 const Identifier* className = 0; 46 const Identifier* className { nullptr }; 47 unsigned startOffset { 0 }; 48 unsigned endOffset { 0 }; 49 int startLine { 0 }; 50 unsigned startColumn { 0 }; 47 51 }; 48 52 -
trunk/Source/JavaScriptCore/parser/SyntaxChecker.h
r197947 r198042 1 1 /* 2 * Copyright (C) 2010, 2013 Apple Inc. All rights reserved.2 * Copyright (C) 2010, 2013, 2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 183 183 ExpressionType createYield(const JSTokenLocation&) { return YieldExpr; } 184 184 ExpressionType createYield(const JSTokenLocation&, ExpressionType, bool, int, int, int) { return YieldExpr; } 185 ClassExpression createClassExpr(const JSTokenLocation&, const Identifier&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList, PropertyList) { return ClassExpr; }185 ClassExpression createClassExpr(const JSTokenLocation&, const ParserClassInfo<SyntaxChecker>&, VariableEnvironment&, ExpressionType, ExpressionType, PropertyList, PropertyList) { return ClassExpr; } 186 186 ExpressionType createFunctionExpr(const JSTokenLocation&, const ParserFunctionInfo<SyntaxChecker>&) { return FunctionExpr; } 187 187 int createFunctionMetadata(const JSTokenLocation&, const JSTokenLocation&, int, int, bool, int, int, int, ConstructorKind, SuperBinding, unsigned, SourceParseMode, bool, InnerArrowFunctionCodeFeatures = NoInnerArrowFunctionFeatures) { return FunctionBodyResult; } -
trunk/Source/JavaScriptCore/runtime/Executable.h
r197867 r198042 1 1 /* 2 * Copyright (C) 2009, 2010, 2013-201 5Apple Inc. All rights reserved.2 * Copyright (C) 2009, 2010, 2013-2016 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 663 663 bool isBuiltinFunction() const { return m_unlinkedExecutable->isBuiltinFunction(); } 664 664 ConstructAbility constructAbility() const { return m_unlinkedExecutable->constructAbility(); } 665 bool isClass() const { return !classSource().isNull(); } 665 666 bool isArrowFunction() const { return parseMode() == SourceParseMode::ArrowFunctionMode; } 666 667 bool isGetter() const { return parseMode() == SourceParseMode::GetterMode; } … … 673 674 size_t parameterCount() const { return m_unlinkedExecutable->parameterCount(); } // Excluding 'this'! 674 675 SourceParseMode parseMode() const { return m_unlinkedExecutable->parseMode(); } 676 const SourceCode& classSource() const { return m_unlinkedExecutable->classSource(); } 675 677 676 678 static void visitChildren(JSCell*, SlotVisitor&); -
trunk/Source/JavaScriptCore/runtime/FunctionPrototype.cpp
r197815 r198042 1 1 /* 2 2 * Copyright (C) 1999-2001 Harri Porten (porten@kde.org) 3 * Copyright (C) 2003 , 2004, 2005, 2006, 2007, 2008, 2009, 2015Apple Inc. All rights reserved.3 * Copyright (C) 2003-2009, 2015-2016 Apple Inc. All rights reserved. 4 4 * 5 5 * This library is free software; you can redistribute it and/or … … 90 90 91 91 FunctionExecutable* executable = function->jsExecutable(); 92 92 if (executable->isClass()) { 93 StringView classSource = executable->classSource().view(); 94 return JSValue::encode(jsString(exec, classSource.toStringWithoutCopying())); 95 } 96 93 97 String functionHeader = executable->isArrowFunction() ? "" : "function "; 94 98 -
trunk/Source/JavaScriptCore/tests/es6.yaml
r198023 r198042 802 802 cmd: runES6 :normal 803 803 - path: es6/function_name_property_object_methods_class.js 804 cmd: runES6 : fail804 cmd: runES6 :normal 805 805 - path: es6/function_name_property_object_methods_function.js 806 806 cmd: runES6 :normal … … 810 810 cmd: runES6 :fail 811 811 - path: es6/function_name_property_variables_class.js 812 cmd: runES6 : fail812 cmd: runES6 :normal 813 813 - path: es6/function_name_property_variables_function.js 814 814 cmd: runES6 :normal
Note:
See TracChangeset
for help on using the changeset viewer.