Initial implementation of class fields (#4191)

Missing features:
 - this binding in static fields are not supported
 - static field evaluation order is wrong
 - function names are not supported

JerryScript-DCO-1.0-Signed-off-by: Zoltan Herczeg zherczeg.u-szeged@partner.samsung.com
This commit is contained in:
Zoltan Herczeg
2020-09-17 15:22:55 +02:00
committed by GitHub
parent 7345c83af7
commit d9653823ca
30 changed files with 1666 additions and 581 deletions
+182
View File
@@ -0,0 +1,182 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
function check_syntax_error(code)
{
try {
eval(code)
assert(false)
} catch (e) {
assert(e instanceof SyntaxError)
}
}
function check_property(obj, name, value)
{
property = Object.getOwnPropertyDescriptor(obj, name)
assert(typeof property === "object")
assert(property.value === value)
}
check_syntax_error("class C { get a = 5 }");
check_syntax_error("class C { id1 id2 }");
check_syntax_error("class C { a = 5,6 }");
check_syntax_error("class C { set\na = 6 }");
check_syntax_error("class C { constructor }");
check_syntax_error("class C { static constructor }");
check_syntax_error("class C { constructor = 1 }");
check_syntax_error("class C { static constructor = 1 }");
check_syntax_error("class C { f = arguments }");
check_syntax_error("class C { static f = a\\u0072guments }");
check_syntax_error("class C { f = () => arguments }");
check_syntax_error("class C { f = arguments => 1 }");
check_syntax_error("class C { f = ([arguments]) => 1 }");
check_syntax_error("new class { f = eval('arguments') }");
check_syntax_error("new class { f = eval('arguments => 1') }");
var res = 10
var counter = 0
function f1() {
counter++
return 5
}
var C1 = class {
get = "a" + f1()
static; set; a = () => Math.cos(0)
v\u0061r
f\u006fr = () => this
arguments = this
}
res = new C1
check_property(res, "get", "a5")
check_property(res, "static", undefined)
check_property(res, "set", undefined)
assert(res.a() === 1)
check_property(res, "var", undefined)
assert(res.for() === res)
assert(res.arguments === res)
class C2 {
constructor(a = this.x, b = this.y) {
assert(a === undefined)
assert(b === undefined)
check_property(this, 'x', 11)
check_property(this, 'y', "ab")
}
x = 5 + 6
y = "a" + 'b'
}
res = new C2
class C3 {
constructor() {
assert(this.x === 1)
return { z:"zz" }
}
x = 1
}
class C4 extends C3 {
constructor() {
super()
assert(Object.getOwnPropertyDescriptor(this, "x") === undefined)
check_property(this, "y", 2)
check_property(this, "z", "zz")
}
y = 2
}
new C4
var o = {}
class C5 extends C3 {
'pr op' = o
3 = true
}
res = new C5
assert(Object.getOwnPropertyDescriptor(res, "x") === undefined)
check_property(res, "pr op", o)
check_property(res, "3", true)
check_property(res, "z", "zz")
class C6 {
a= () => this
b= this
}
class C7 extends C6 {
c= () => this
d= this
}
count = 0
class C8 extends C7 {
constructor() {
count++
super()
}
e= () => this
f= this
}
var res = new C8
assert(res.a() === res)
assert(res.b === res)
assert(res.c() === res)
assert(res.d === res)
assert(res.e() === res)
assert(res.f === res)
count = 0
class C9 {
a=assert(++count === 5)
a=assert(++count === 6)
a=assert(++count === 7)
a=assert(++count === 8)
static a=assert(++count === 1)
static a=assert(++count === 2)
static a=assert(++count === 3)
static a=assert(++count === 4)
}
assert(count === 4)
new C9
assert(count === 8)
count = 0
class C10 {
[(assert(++count == 1), "aa")] = assert(++count == 5);
[(assert(++count == 2), "bb")] = assert(++count == 6);
cc = assert(++count == 7);
[(assert(++count == 3), "aa")] = assert(++count == 8);
[(assert(++count == 4), "bb")] = assert(++count == 9);
}
assert(count == 4)
assert(Reflect.ownKeys(new C10).toString() === "aa,bb,cc");
assert(count == 9)
res = "p"
class C11 {
p1 = assert(Reflect.ownKeys(this).toString() === "");
[res + 2] = assert(Reflect.ownKeys(this).toString() === "p1");
[res + 1] = assert(Reflect.ownKeys(this).toString() === "p1,p2");
p3 = assert(Reflect.ownKeys(this).toString() === "p1,p2");
[res + 4] = assert(Reflect.ownKeys(this).toString() === "p1,p2,p3");
}
new C11
+139
View File
@@ -0,0 +1,139 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
var count = 0
class C1 {
error = assert(++count === 1)
error = function() { throw 40.5 }()
}
try {
new C1
assert(false)
} catch(e) {
assert(e === 40.5)
assert(count === 1)
}
count = 0
class C2 {
constructor(a = assert(++count === 1)) {}
error = function() { throw "Err" }()
error = assert(false)
}
try {
new C2
assert(false)
} catch(e) {
assert(e === "Err")
assert(count === 1)
}
count = 0
var o = {}
class C3 extends class {
error = function() { throw o }()
} {
constructor() {
assert(++count === 1)
super()
assert(false)
}
}
try {
new C3
assert(false)
} catch (e) {
assert(e === o)
assert(count === 1)
}
count = 0
class C4 {
constructor() {
assert(++count === 2)
}
a = assert(++count === 1)
}
class C5 extends C4 {
ok = assert(++count === 3)
error = function() { assert(++count === 4); throw "Except" }()
never = assert(false)
}
try {
new C5
assert(false)
} catch (e) {
assert(e === "Except")
assert(count === 4)
}
count = 0
o = []
class C6 {
a = assert(++count === 2)
}
class C7 extends C6 {
constructor() {
assert(++count === 1)
eval('super()')
assert(false)
}
ok = assert(++count === 3)
error = function() { assert(++count === 4); throw o }()
never = assert(false)
}
try {
new C7
assert(false)
} catch (e) {
assert(e === o)
assert(count === 4)
}
var res
class C8 {
/* Create a non-configurable accessor */
a = (res = this, Object.defineProperty(this, "b", { get() {} }));
b = 6
}
try {
new C8
assert(false)
} catch(e) {
assert(e instanceof TypeError)
assert(Reflect.ownKeys(res).toString() === "b,a")
}
class C9 {
["p" + 1]
["p" + 2] = (res = this, Object.freeze(this));
p3
}
try {
new C9
assert(false)
} catch(e) {
assert(e instanceof TypeError)
assert(Reflect.ownKeys(res).toString() === "p1")
}
+53
View File
@@ -0,0 +1,53 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
function check_property(obj, name, value)
{
property = Object.getOwnPropertyDescriptor(obj, name)
assert(typeof property === "object")
assert(property.value === value)
}
var o = {}
var name = "Pro"
var res = 0
var counter = 0
function f1() {
counter++
}
class C1 {
static
v\u0061r
static Prop =
res
=
"msg"
static
Prop
=
f1()
static [name + "p"] = (f1(), o)
static 22 = 3 * 4 ;static 23 = 5 + 6
static 'a b'
}
check_property(C1, "var", undefined)
check_property(C1, "Prop", o)
check_property(C1, 22, 12)
check_property(C1, 23, 11)
check_property(C1, "a b", undefined)
assert(res === "msg")
assert(counter === 2)
+31
View File
@@ -0,0 +1,31 @@
/* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var called = false
var obj = { f() { assert(this === obj); called = true } }
function f() {
assert(false)
}
with (obj) {
new class {
constructor() {
f()
}
}
}
assert(called)
@@ -1,20 +0,0 @@
// Copyright JS Foundation and other contributors, http://js.foundation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
try {
eval("class cla { static }");
assert(false);
} catch (e) {
assert(e instanceof SyntaxError);
}