Skip to content

Commit c9cb591

Browse files
committed
[JSC] Implement private static method
https://bugs.webkit.org/show_bug.cgi?id=219181 Reviewed by Yusuke Suzuki. JSTests: * stress/class-private-method-access.js: Added. * stress/private-accessor-static-non-static.js: Added. * stress/private-getter-inner-class.js: * stress/static-private-methods-and-accessor-inner-class.js: Added. * stress/static-private-methods-and-accessor-multiple-evaluation.js: Added. * stress/static-private-methods-and-accessors-postfix-node.js: Added. * stress/static-private-methods-and-accessors-prefix-node.js: Added. * test262/config.yaml: Source/JavaScriptCore: This patch is implementing static private methods and accessors proposal based on https://github.com/tc39/proposal-static-class-features. This implementation diverge a bit from private methods&accessors on the brand check, because we are using a simpler way to perform static brand checks. Since only the class constructor is allowed to access its private methods and accessors, we save it on `@privateClassBrand` on class lexical scope and compare it with the receiver of the static private method (and accessors) using `===` operation. While this genenrates more bytecodes than `check_private_brand`, we don't need to perform a Structure transition to install a brand, and avoid allocation of a private symbol. Since each evaluation of a class generates a different constructor object, we preserve the semantics that private methods are lexically scoped. * builtins/BuiltinNames.h: * bytecompiler/BytecodeGenerator.cpp: (JSC::BytecodeGenerator::emitCreatePrivateBrand): (JSC::BytecodeGenerator::emitInstallPrivateBrand): (JSC::BytecodeGenerator::emitInstallPrivateClassBrand): (JSC::BytecodeGenerator::emitGetPrivateBrand): (JSC::BytecodeGenerator::emitCheckPrivateBrand): * bytecompiler/BytecodeGenerator.h: * bytecompiler/NodesCodegen.cpp: (JSC::BaseDotNode::emitGetPropertyValue): (JSC::BaseDotNode::emitPutProperty): (JSC::PostfixNode::emitDot): (JSC::PrefixNode::emitDot): (JSC::ClassExprNode::emitBytecode): * parser/Parser.cpp: (JSC::Parser<LexerType>::parseClass): (JSC::Parser<LexerType>::parseGetterSetter): * parser/Parser.h: (JSC::Scope::declarePrivateMethod): (JSC::Scope::declarePrivateAccessor): (JSC::Scope::declarePrivateSetter): (JSC::Scope::declarePrivateGetter): * parser/VariableEnvironment.cpp: (JSC::VariableEnvironment::declarePrivateAccessor): (JSC::VariableEnvironment::declarePrivateSetter): (JSC::VariableEnvironment::declarePrivateGetter): (JSC::VariableEnvironment::declarePrivateMethod): * parser/VariableEnvironment.h: (JSC::PrivateNameEntry::isStatic const): (JSC::VariableEnvironment::isEmpty const): (JSC::VariableEnvironment::declareStaticPrivateMethod): (JSC::VariableEnvironment::declarePrivateSetter): (JSC::VariableEnvironment::declareStaticPrivateSetter): (JSC::VariableEnvironment::declarePrivateGetter): (JSC::VariableEnvironment::declareStaticPrivateGetter): (JSC::VariableEnvironment::hasStaticPrivateMethodOrAccessor const): (JSC::VariableEnvironment::hasInstancePrivateMethodOrAccessor const): (JSC::VariableEnvironment::hasPrivateMethodOrAccessor const): Deleted. Canonical link: https://commits.webkit.org/234304@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@273107 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent 7883bd1 commit c9cb591

18 files changed

Lines changed: 1050 additions & 99 deletions

‎JSTests/ChangeLog‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
2021-02-18 Caio Lima <ticaiolima@gmail.com>
2+
3+
[JSC] Implement private static method
4+
https://bugs.webkit.org/show_bug.cgi?id=219181
5+
6+
Reviewed by Yusuke Suzuki.
7+
8+
* stress/class-private-method-access.js: Added.
9+
* stress/private-accessor-static-non-static.js: Added.
10+
* stress/private-getter-inner-class.js:
11+
* stress/static-private-methods-and-accessor-inner-class.js: Added.
12+
* stress/static-private-methods-and-accessor-multiple-evaluation.js: Added.
13+
* stress/static-private-methods-and-accessors-postfix-node.js: Added.
14+
* stress/static-private-methods-and-accessors-prefix-node.js: Added.
15+
* test262/config.yaml:
16+
117
2021-02-18 Michael Saboff <msaboff@apple.com>
218

319
[JSC] Implement RegExp Match Indices proposal
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
//@ requireOptions("--usePrivateMethods=true")
2+
3+
function assert(a, e) {
4+
if (a !== e)
5+
throw new Error("Expected: " + e + " but got: " + a);
6+
}
7+
8+
function assertThrows(expectedError, f) {
9+
try {
10+
f();
11+
} catch (e) {
12+
assert(e instanceof expectedError, true);
13+
}
14+
}
15+
16+
(() => {
17+
class C {
18+
static get #m() {
19+
return 'static';
20+
}
21+
22+
static staticAccess() {
23+
return this.#m;
24+
}
25+
26+
get #f() {
27+
return 'instance';
28+
}
29+
30+
instanceAccess() {
31+
return this.#f;
32+
}
33+
}
34+
35+
let c = new C();
36+
assert(C.staticAccess(), 'static');
37+
assert(c.instanceAccess(), 'instance');
38+
39+
assertThrows(TypeError, () => {
40+
C.staticAccess.call(c);
41+
});
42+
43+
assertThrows(TypeError, () => {
44+
c.instanceAccess.call(C);
45+
});
46+
})();
47+
48+
(() => {
49+
class C {
50+
static #m() {
51+
return 'static';
52+
}
53+
54+
static staticAccess() {
55+
return this.#m();
56+
}
57+
58+
#f() {
59+
return 'instance';
60+
}
61+
62+
instanceAccess() {
63+
return this.#f();
64+
}
65+
}
66+
67+
let c = new C();
68+
assert(C.staticAccess(), 'static');
69+
assert(c.instanceAccess(), 'instance');
70+
71+
assertThrows(TypeError, () => {
72+
C.staticAccess.call(c);
73+
});
74+
75+
assertThrows(TypeError, () => {
76+
c.instanceAccess.call(C);
77+
});
78+
})();
79+
80+
(() => {
81+
class C {
82+
static set #m(v) {
83+
this._m = v;
84+
}
85+
86+
static staticAccess() {
87+
this.#m = 'static';
88+
}
89+
90+
set #f(v) {
91+
this._f = v;
92+
}
93+
94+
instanceAccess() {
95+
this.#f = 'instance';
96+
}
97+
}
98+
99+
let c = new C();
100+
C.staticAccess();
101+
assert(C._m, 'static');
102+
c.instanceAccess()
103+
assert(c._f, 'instance');
104+
105+
assertThrows(TypeError, () => {
106+
C.staticAccess.call(c);
107+
});
108+
109+
assertThrows(TypeError, () => {
110+
c.instanceAccess.call(C);
111+
});
112+
})();
113+
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//@ run("--useClassFields=true --usePrivateMethods=true")
2+
3+
function assert(a, e, m) {
4+
if (a !== e)
5+
throw new Error(m);
6+
}
7+
8+
function assertSyntaxError(code) {
9+
try {
10+
eval(code);
11+
throw new Error("Code executed without throwing SyntaxError");
12+
} catch (e) {
13+
assert(e instanceof SyntaxError, true, e.message);
14+
}
15+
}
16+
17+
assertSyntaxError(`
18+
class C {
19+
static get #m() {}
20+
set #m(v) {}
21+
}
22+
`);
23+
24+
assertSyntaxError(`
25+
class C {
26+
get #m() {}
27+
static set #m(v) {}
28+
}
29+
`);
30+
31+
assertSyntaxError(`
32+
class C {
33+
static set #m(v) {}
34+
get #m() {}
35+
}
36+
`);
37+
38+
assertSyntaxError(`
39+
class C {
40+
set #m(v) {}
41+
static get #m() {}
42+
}
43+
`);
44+

‎JSTests/stress/private-getter-inner-class.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ let assert = {
126126
assert.sameValue(c.method(), 'outer class');
127127

128128
assert.throws(TypeError, function() {
129-
innerB.method(c);
129+
C.prototype.method.call(innerB);
130130
});
131131
})();
132132

0 commit comments

Comments
 (0)