WebKit Bugzilla
Attachment 370694 Details for
Bug 194434
: [ESNext] Implement private methods
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
WIP - Patch
private_methods.diff (text/plain), 80.57 KB, created by
Caio Lima
on 2019-05-27 08:55:23 PDT
(
hide
)
Description:
WIP - Patch
Filename:
MIME Type:
Creator:
Caio Lima
Created:
2019-05-27 08:55:23 PDT
Size:
80.57 KB
patch
obsolete
>diff --git a/JSTests/stress/private-method-brand-check.js b/JSTests/stress/private-method-brand-check.js >new file mode 100644 >index 00000000000..593abb3fbe5 >--- /dev/null >+++ b/JSTests/stress/private-method-brand-check.js >@@ -0,0 +1,33 @@ >+//@ run("--useClassFields=true --usePrivateMethods=true") >+ >+function assert(a, e) { >+ if (a !== e) >+ throw new Error("Expected: " + e + " but got: " + a); >+} >+ >+class C { >+ #m() { >+ return this.#f; >+ } >+ >+ method() { >+ return this.#m(); >+ } >+ >+ #f = 4; >+} >+ >+let c = new C(); >+assert(c.method(), 4); >+ >+try { >+ class C { >+ #m() { return 3; } >+ } >+ >+ let o = new C(); >+ c.method.call(o); >+} catch (e) { >+ assert(e instanceof TypeError, true); >+} >+ >diff --git a/JSTests/stress/private-method-comparison.js b/JSTests/stress/private-method-comparison.js >new file mode 100644 >index 00000000000..c05501ae889 >--- /dev/null >+++ b/JSTests/stress/private-method-comparison.js >@@ -0,0 +1,31 @@ >+//@ run("--useClassFields=true --usePrivateMethods=true") >+ >+let assert = { >+ sameValue: function (lhs, rhs) { >+ if (lhs !== rhs) >+ throw new Error("Expected: " + lhs + " bug got: " + rhs); >+ }, >+ >+ throws: function (expectedError, op) { >+ try { >+ op(); >+ } catch(e) { >+ if (!(e instanceof expectedError)) >+ throw new Error("Expected to throw: " + expectedError + " but threw: " + e); >+ } >+ } >+}; >+ >+class C { >+ #m() { return 'test262'; } >+ >+ getPrivateMethod() { >+ return this.#m; >+ } >+} >+ >+let c1 = new C(); >+let c2 = new C(); >+ >+assert.sameValue(c1.getPrivateMethod(), c2.getPrivateMethod()); >+ >diff --git a/JSTests/stress/private-method-extends-brand-check.js b/JSTests/stress/private-method-extends-brand-check.js >new file mode 100644 >index 00000000000..747efc3f9a9 >--- /dev/null >+++ b/JSTests/stress/private-method-extends-brand-check.js >@@ -0,0 +1,41 @@ >+//@ run("--useClassFields=true --usePrivateMethods=true") >+ >+function assert(a, e) { >+ if (a !== e) >+ throw new Error("Expected: " + e + " but got: " + a); >+} >+ >+class Base { >+ #mBase() { >+ return 4; >+ } >+ >+ methodBase() { >+ return this.#mBase(); >+ } >+} >+ >+class C extends Base { >+ #m() { >+ return this.#f; >+ } >+ >+ method() { >+ return this.#m(); >+ } >+ >+ #f = 15; >+} >+ >+let c = new C(); >+assert(c.method(), 15); >+assert(c.methodBase(), 4); >+ >+let base = new Base (); >+assert(base.methodBase(), 4); >+try { >+ c.method.call(base); >+} catch (e) { >+ assert(e instanceof TypeError, true); >+} >+ >diff --git a/JSTests/stress/private-method-get-and-call.js b/JSTests/stress/private-method-get-and-call.js >new file mode 100644 >index 00000000000..cf8d2c14e32 >--- /dev/null >+++ b/JSTests/stress/private-method-get-and-call.js >@@ -0,0 +1,33 @@ >+//@ run("--useClassFields=true --usePrivateMethods=true") >+ >+let assert = { >+ sameValue: function (lhs, rhs) { >+ if (lhs !== rhs) >+ throw new Error("Expected: " + lhs + " bug got: " + rhs); >+ }, >+ >+ throws: function (expectedError, op) { >+ try { >+ op(); >+ } catch(e) { >+ if (!(e instanceof expectedError)) >+ throw new Error("Expected to throw: " + expectedError + " but threw: " + e); >+ } >+ } >+}; >+ >+class C { >+ #m() { return this._v; } >+ >+ getPrivateMethod() { >+ return this.#m; >+ } >+} >+ >+let c = new C(); >+ >+let o1 = {_v: 'test262'}; >+let o2 = {_v: 'foo'}; >+assert.sameValue(c.getPrivateMethod().call(o1), 'test262'); >+assert.sameValue(c.getPrivateMethod().call(o2), 'foo'); >+ >diff --git a/JSTests/stress/private-method-nested-class.js b/JSTests/stress/private-method-nested-class.js >new file mode 100644 >index 00000000000..e6c9948c1b3 >--- /dev/null >+++ b/JSTests/stress/private-method-nested-class.js >@@ -0,0 +1,68 @@ >+//@ run("--useClassFields=true --usePrivateMethods=true") >+ >+function assert(a, e) { >+ if (a !== e) >+ throw new Error("Expected: " + e + " but got: " + a); >+} >+ >+(() => { >+ class Base { >+ C = class { >+ method() { >+ return this.#mBase(); >+ } >+ } >+ >+ #mBase() { >+ return 4; >+ } >+ } >+ >+ let base = new Base(); >+ let c = new base.C(); >+ assert(c.method.call(base), 4); >+ >+ try { >+ c.method(); >+ } catch (e) { >+ assert(e instanceof TypeError, true); >+ } >+})(); >+ >+// Test shadow methods >+ >+(() => { >+ class Base { >+ method() { >+ return this.#m(); >+ } >+ >+ C = class { >+ method(o) { >+ return o.#m(); >+ } >+ >+ #m() { >+ return this.foo; >+ } >+ >+ foo = 4; >+ }; >+ >+ #m() { >+ return "foo"; >+ } >+ } >+ >+ let base = new Base(); >+ let c = new base.C(); >+ assert(c.method(c), 4); >+ assert(base.method(), "foo"); >+ >+ try { >+ c.method(base); >+ } catch (e) { >+ assert(e instanceof TypeError, true); >+ } >+})(); >+ >diff --git a/JSTests/stress/private-methods-on-proxy.js b/JSTests/stress/private-methods-on-proxy.js >new file mode 100644 >index 00000000000..aeb89b106a8 >--- /dev/null >+++ b/JSTests/stress/private-methods-on-proxy.js >@@ -0,0 +1,42 @@ >+//@ run("--useClassFields=true --usePrivateMethods=true") >+ >+function assert(a, e, m) { >+ if (a !== e) >+ throw new Error(m); >+} >+ >+function assertArrayContent(a, e) { >+ assert(a.length, e.length, "Size of arrays doesn't match"); >+ for (var i = 0; i < a.length; i++) >+ assert(a[i], e[i], "a[" + i + "] = " + a[i] + " but e[" + i + "] = " + e[i]); >+} >+ >+let arr = []; >+ >+class ProxyBase { >+ constructor() { >+ return new Proxy(this, { >+ get: function (obj, prop) { >+ arr.push(prop); >+ return obj[prop]; >+ } >+ }); >+ } >+} >+ >+class Test extends ProxyBase { >+ #m() { >+ return 3; >+ } >+ >+ method() { >+ return this.#m(); >+ } >+} >+ >+let t = new Test(); >+let r = t.method(); >+assert(r, 3, "Expected: 3 but got: " + r); >+ >+assertArrayContent(arr, ['method']); >+ >diff --git a/JSTests/stress/private-names-available-on-direct-eval.js b/JSTests/stress/private-names-available-on-direct-eval.js >new file mode 100644 >index 00000000000..e2707210dac >--- /dev/null >+++ b/JSTests/stress/private-names-available-on-direct-eval.js >@@ -0,0 +1,23 @@ >+//@ run("--useClassFields=true --usePrivateMethods=true") >+ >+let assert = { >+ sameValue: function (lhs, rhs) { >+ if (lhs !== rhs) >+ throw new Error("Expected: " + rhs + " bug got: " + lhs); >+ } >+}; >+ >+(function () { >+ class C { >+ #m() { return 'test'; } >+ >+ callMethodFromEval() { >+ let self = this; >+ return eval('self.#m()'); >+ } >+ } >+ >+ let c = new C(); >+ assert.sameValue(c.callMethodFromEval(), 'test'); >+})(); >+ >diff --git a/JSTests/test262/config.yaml b/JSTests/test262/config.yaml >index b12c221248f..ad6d0f25760 100644 >--- a/JSTests/test262/config.yaml >+++ b/JSTests/test262/config.yaml >@@ -17,7 +17,6 @@ skip: > - Symbol.matchAll > # https://bugs.webkit.org/show_bug.cgi?id=174931 > - regexp-lookbehind >- - class-methods-private > - class-static-fields-public > - class-static-fields-private > - class-static-methods-private >diff --git a/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp b/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp >index fef4122603b..7d8a3793fda 100644 >--- a/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp >+++ b/Source/JavaScriptCore/builtins/BuiltinExecutables.cpp >@@ -58,14 +58,14 @@ SourceCode BuiltinExecutables::defaultConstructorSourceCode(ConstructorKind cons > return SourceCode(); > } > >-UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name) >+UnlinkedFunctionExecutable* BuiltinExecutables::createDefaultConstructor(ConstructorKind constructorKind, const Identifier& name, PrivateBrandRequirement privateBrandRequirement) > { > switch (constructorKind) { > case ConstructorKind::None: > break; > case ConstructorKind::Base: > case ConstructorKind::Extends: >- return createExecutable(m_vm, defaultConstructorSourceCode(constructorKind), name, constructorKind, ConstructAbility::CanConstruct); >+ return createExecutable(m_vm, defaultConstructorSourceCode(constructorKind), name, constructorKind, ConstructAbility::CanConstruct, privateBrandRequirement); > } > ASSERT_NOT_REACHED(); > return nullptr; >@@ -81,7 +81,7 @@ UnlinkedFunctionExecutable* createBuiltinExecutable(VM& vm, const SourceCode& co > return BuiltinExecutables::createExecutable(vm, code, name, ConstructorKind::None, constructAbility); > } > >-UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility) >+UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const SourceCode& source, const Identifier& name, ConstructorKind constructorKind, ConstructAbility constructAbility, PrivateBrandRequirement privateBrandRequirement) > { > // FIXME: Can we just make MetaData computation be constexpr and have the compiler do this for us? > // https://bugs.webkit.org/show_bug.cgi?id=193272 >@@ -254,7 +254,7 @@ UnlinkedFunctionExecutable* BuiltinExecutables::createExecutable(VM& vm, const S > } > } > >- UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, WTF::nullopt, DerivedContextType::None, isBuiltinDefaultClassConstructor); >+ UnlinkedFunctionExecutable* functionExecutable = UnlinkedFunctionExecutable::create(&vm, source, &metadata, kind, constructAbility, JSParserScriptMode::Classic, WTF::nullopt, DerivedContextType::None, privateBrandRequirement, isBuiltinDefaultClassConstructor); > return functionExecutable; > } > >diff --git a/Source/JavaScriptCore/builtins/BuiltinExecutables.h b/Source/JavaScriptCore/builtins/BuiltinExecutables.h >index aa4433c6cec..949ae2d7b0c 100644 >--- a/Source/JavaScriptCore/builtins/BuiltinExecutables.h >+++ b/Source/JavaScriptCore/builtins/BuiltinExecutables.h >@@ -57,12 +57,11 @@ SourceCode name##Source(); > #undef EXPOSE_BUILTIN_EXECUTABLES > > static SourceCode defaultConstructorSourceCode(ConstructorKind); >- UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name); >- >- static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility); >+ UnlinkedFunctionExecutable* createDefaultConstructor(ConstructorKind, const Identifier& name, PrivateBrandRequirement); > >+ static UnlinkedFunctionExecutable* createExecutable(VM&, const SourceCode&, const Identifier&, ConstructorKind, ConstructAbility, PrivateBrandRequirement = PrivateBrandRequirement::None); >+ > void finalizeUnconditionally(); >- > private: > VM& m_vm; > >diff --git a/Source/JavaScriptCore/builtins/BuiltinNames.h b/Source/JavaScriptCore/builtins/BuiltinNames.h >index b8fa7061455..4296f3a5789 100644 >--- a/Source/JavaScriptCore/builtins/BuiltinNames.h >+++ b/Source/JavaScriptCore/builtins/BuiltinNames.h >@@ -72,6 +72,7 @@ namespace JSC { > macro(getOwnPropertyNames) \ > macro(ownKeys) \ > macro(Set) \ >+ macro(createPrivateSymbol) \ > macro(typedArrayLength) \ > macro(typedArraySort) \ > macro(typedArrayGetOriginalConstructor) \ >@@ -174,6 +175,7 @@ namespace JSC { > macro(meta) \ > macro(webAssemblyCompileStreamingInternal) \ > macro(webAssemblyInstantiateStreamingInternal) \ >+ macro(privateBrand) \ > macro(instanceFieldInitializer) > > namespace Symbols { >diff --git a/Source/JavaScriptCore/bytecode/BytecodeList.rb b/Source/JavaScriptCore/bytecode/BytecodeList.rb >index 133a20253ea..ad2cac5c3e0 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeList.rb >+++ b/Source/JavaScriptCore/bytecode/BytecodeList.rb >@@ -503,6 +503,12 @@ op :get_by_val, > arrayProfile: ArrayProfile, > } > >+op :check_private_brand, >+ args: { >+ base: VirtualRegister, >+ brand: VirtualRegister, >+ } >+ > op :put_by_val, > args: { > base: VirtualRegister, >diff --git a/Source/JavaScriptCore/bytecode/BytecodeUseDef.h b/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >index 1e20cb93619..7926e2c6d11 100644 >--- a/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >+++ b/Source/JavaScriptCore/bytecode/BytecodeUseDef.h >@@ -255,6 +255,7 @@ void computeUsesForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, const Ins > USES(OpAddPrivateField, base, value, scope) > USES(OpGetPrivateField, base, scope) > USES(OpPutPrivateField, base, value, scope) >+ USES(OpCheckPrivateBrand, base, brand) > > case op_new_array_with_spread: > handleNewArrayLike(instruction->as<OpNewArrayWithSpread>()); >@@ -355,6 +356,7 @@ void computeDefsForBytecodeOffset(Block* codeBlock, OpcodeID opcodeID, const Ins > case op_super_sampler_end: > case op_add_private_field: > case op_put_private_field: >+ case op_check_private_brand: > #define LLINT_HELPER_OPCODES(opcode, length) case opcode: > FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES); > #undef LLINT_HELPER_OPCODES >diff --git a/Source/JavaScriptCore/bytecode/ExecutableInfo.h b/Source/JavaScriptCore/bytecode/ExecutableInfo.h >index 41be844c7a5..eb1736e0df7 100644 >--- a/Source/JavaScriptCore/bytecode/ExecutableInfo.h >+++ b/Source/JavaScriptCore/bytecode/ExecutableInfo.h >@@ -35,10 +35,11 @@ enum class EvalContextType : uint8_t { None, FunctionEvalContext, InstanceFie > // FIXME: These flags, ParserModes and propagation to XXXCodeBlocks should be reorganized. > // https://bugs.webkit.org/show_bug.cgi?id=151547 > struct ExecutableInfo { >- ExecutableInfo(bool usesEval, bool isStrictMode, bool isConstructor, bool isBuiltinFunction, ConstructorKind constructorKind, JSParserScriptMode scriptMode, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, bool isClassContext, EvalContextType evalContextType) >+ ExecutableInfo(bool usesEval, bool isStrictMode, bool isConstructor, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinFunction, ConstructorKind constructorKind, JSParserScriptMode scriptMode, SuperBinding superBinding, SourceParseMode parseMode, DerivedContextType derivedContextType, bool isArrowFunctionContext, bool isClassContext, EvalContextType evalContextType) > : m_usesEval(usesEval) > , m_isStrictMode(isStrictMode) > , m_isConstructor(isConstructor) >+ , m_privateBrandRequirement(static_cast<unsigned>(privateBrandRequirement)) > , m_isBuiltinFunction(isBuiltinFunction) > , m_constructorKind(static_cast<unsigned>(constructorKind)) > , m_superBinding(static_cast<unsigned>(superBinding)) >@@ -57,6 +58,7 @@ struct ExecutableInfo { > bool usesEval() const { return m_usesEval; } > bool isStrictMode() const { return m_isStrictMode; } > bool isConstructor() const { return m_isConstructor; } >+ PrivateBrandRequirement privateBrandRequirement() const { return static_cast<PrivateBrandRequirement>(m_privateBrandRequirement); } > bool isBuiltinFunction() const { return m_isBuiltinFunction; } > ConstructorKind constructorKind() const { return static_cast<ConstructorKind>(m_constructorKind); } > SuperBinding superBinding() const { return static_cast<SuperBinding>(m_superBinding); } >@@ -71,6 +73,7 @@ private: > unsigned m_usesEval : 1; > unsigned m_isStrictMode : 1; > unsigned m_isConstructor : 1; >+ unsigned m_privateBrandRequirement : 1; > unsigned m_isBuiltinFunction : 1; > unsigned m_constructorKind : 2; > unsigned m_superBinding : 1; >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >index f9c3ba9d716..d2dd1f93bf9 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp >@@ -59,6 +59,7 @@ UnlinkedCodeBlock::UnlinkedCodeBlock(VM* vm, Structure* structure, CodeType code > , m_usesEval(info.usesEval()) > , m_isStrictMode(info.isStrictMode()) > , m_isConstructor(info.isConstructor()) >+ , m_privateBrandRequirement(static_cast<unsigned>(info.privateBrandRequirement())) > , m_hasCapturedVariables(false) > , m_isBuiltinFunction(info.isBuiltinFunction()) > , m_superBinding(static_cast<unsigned>(info.superBinding())) >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >index 2a350a1f11c..7d902812fe3 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h >@@ -116,6 +116,7 @@ public: > enum { CallFunction, ApplyFunction }; > > bool isConstructor() const { return m_isConstructor; } >+ PrivateBrandRequirement privateBrandRequirement() const { return static_cast<PrivateBrandRequirement>(m_privateBrandRequirement); } > bool isStrictMode() const { return m_isStrictMode; } > bool usesEval() const { return m_usesEval; } > SourceParseMode parseMode() const { return m_parseMode; } >@@ -412,6 +413,7 @@ private: > unsigned m_usesEval : 1; > unsigned m_isStrictMode : 1; > unsigned m_isConstructor : 1; >+ unsigned m_privateBrandRequirement : 1; > unsigned m_hasCapturedVariables : 1; > unsigned m_isBuiltinFunction : 1; > unsigned m_superBinding : 1; >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp >index 33b0f43da8a..e36349d1f1f 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp >+++ b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.cpp >@@ -72,7 +72,7 @@ static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock( > > bool isClassContext = executable->superBinding() == SuperBinding::Needed; > >- UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), scriptMode, executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext, EvalContextType::FunctionEvalContext), codeGenerationMode); >+ UnlinkedFunctionCodeBlock* result = UnlinkedFunctionCodeBlock::create(&vm, FunctionCode, ExecutableInfo(function->usesEval(), function->isStrictMode(), kind == CodeForConstruct, executable->privateBrandRequirement(), functionKind == UnlinkedBuiltinFunction, executable->constructorKind(), scriptMode, executable->superBinding(), parseMode, executable->derivedContextType(), false, isClassContext, EvalContextType::FunctionEvalContext), codeGenerationMode); > > VariableEnvironment parentScopeTDZVariables = executable->parentScopeTDZVariables(); > error = BytecodeGenerator::generate(vm, function.get(), source, result, codeGenerationMode, &parentScopeTDZVariables); >@@ -83,7 +83,7 @@ static UnlinkedFunctionCodeBlock* generateUnlinkedFunctionCodeBlock( > return result; > } > >-UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor) >+UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* structure, const SourceCode& parentSource, FunctionMetadataNode* node, UnlinkedFunctionKind kind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, PrivateBrandRequirement privateBrandRequirement, bool isBuiltinDefaultClassConstructor) > : Base(*vm, structure) > , m_firstLineOffset(node->firstLine() - parentSource.firstLine().oneBasedInt()) > , m_lineCount(node->lastLine() - node->firstLine()) >@@ -108,6 +108,7 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* struct > , m_scriptMode(static_cast<unsigned>(scriptMode)) > , m_superBinding(static_cast<unsigned>(node->superBinding())) > , m_derivedContextType(static_cast<unsigned>(derivedContextType)) >+ , m_privateBrandRequirement(static_cast<unsigned>(privateBrandRequirement)) > , m_isCached(false) > , m_unlinkedCodeBlockForCall() > , m_unlinkedCodeBlockForConstruct() >@@ -122,6 +123,7 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* struct > ASSERT(m_scriptMode == static_cast<unsigned>(scriptMode)); > ASSERT(m_superBinding == static_cast<unsigned>(node->superBinding())); > ASSERT(m_derivedContextType == static_cast<unsigned>(derivedContextType)); >+ ASSERT(m_privateBrandRequirement == static_cast<unsigned>(privateBrandRequirement)); > ASSERT(!(m_isBuiltinDefaultClassConstructor && constructorKind() == ConstructorKind::None)); > if (!node->classSource().isNull()) > setClassSource(node->classSource()); >diff --git a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >index f35aadf2194..b03b086cef7 100644 >--- a/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >+++ b/Source/JavaScriptCore/bytecode/UnlinkedFunctionExecutable.h >@@ -69,10 +69,10 @@ public: > return &vm.unlinkedFunctionExecutableSpace.space; > } > >- static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, bool isBuiltinDefaultClassConstructor = false) >+ static UnlinkedFunctionExecutable* create(VM* vm, const SourceCode& source, FunctionMetadataNode* node, UnlinkedFunctionKind unlinkedFunctionKind, ConstructAbility constructAbility, JSParserScriptMode scriptMode, Optional<CompactVariableMap::Handle> parentScopeTDZVariables, DerivedContextType derivedContextType, PrivateBrandRequirement privateBrandRequirement = PrivateBrandRequirement::None, bool isBuiltinDefaultClassConstructor = false) > { > UnlinkedFunctionExecutable* instance = new (NotNull, allocateCell<UnlinkedFunctionExecutable>(vm->heap)) >- UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, scriptMode, WTFMove(parentScopeTDZVariables), derivedContextType, isBuiltinDefaultClassConstructor); >+ UnlinkedFunctionExecutable(vm, vm->unlinkedFunctionExecutableStructure.get(), source, node, unlinkedFunctionKind, constructAbility, scriptMode, WTFMove(parentScopeTDZVariables), derivedContextType, privateBrandRequirement, isBuiltinDefaultClassConstructor); > instance->finishCreation(*vm); > return instance; > } >@@ -145,6 +145,8 @@ public: > CodeFeatures features() const { return m_features; } > bool hasCapturedVariables() const { return m_hasCapturedVariables; } > >+ PrivateBrandRequirement privateBrandRequirement() const { return static_cast<PrivateBrandRequirement>(m_privateBrandRequirement); } >+ > static const bool needsDestruction = true; > static void destroy(JSCell*); > >@@ -216,7 +218,7 @@ public: > } > > private: >- UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional<CompactVariableMap::Handle>, JSC::DerivedContextType, bool isBuiltinDefaultClassConstructor); >+ UnlinkedFunctionExecutable(VM*, Structure*, const SourceCode&, FunctionMetadataNode*, UnlinkedFunctionKind, ConstructAbility, JSParserScriptMode, Optional<CompactVariableMap::Handle>, JSC::DerivedContextType, PrivateBrandRequirement, bool isBuiltinDefaultClassConstructor); > UnlinkedFunctionExecutable(Decoder&, const CachedFunctionExecutable&); > > void decodeCachedCodeBlocks(); >@@ -244,6 +246,7 @@ private: > unsigned m_scriptMode: 1; // JSParserScriptMode > unsigned m_superBinding : 1; > unsigned m_derivedContextType: 2; >+ unsigned m_privateBrandRequirement : 1; > bool m_isCached : 1; > > union { >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >index 692b36ddc8f..d62de78ea01 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp >@@ -393,6 +393,8 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke > { > for (auto& constantRegister : m_linkTimeConstantRegisters) > constantRegister = nullptr; >+ >+ pushPrivateAccessNames(*parentScopeTDZVariables); > > allocateCalleeSaveSpace(); > >@@ -736,8 +738,17 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionNode* functionNode, Unlinke > } else > emitCreateThis(&m_thisRegister); > >- if (Options::useClassFields() && constructorKind() == ConstructorKind::Base) >+ if (Options::useClassFields() && constructorKind() == ConstructorKind::Base) { >+ bool shouldEmitPrivateBrand = privateBrandRequirement() == PrivateBrandRequirement::Needed; >+ if (shouldEmitPrivateBrand) { >+ JSTextPosition divot(m_scopeNode->firstLine(), m_scopeNode->startOffset(), m_scopeNode->lineStartOffset()); >+ Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName()); >+ RefPtr<RegisterID> privateBrandVarScope = emitResolveScope(nullptr, privateBrandVar); >+ RegisterID* privateBrandSymbol = emitGetPrivateBrand(newTemporary(), privateBrandVarScope.get()); >+ emitDirectPutByVal(&m_thisRegister, privateBrandSymbol, privateBrandSymbol); >+ } > emitInstanceFieldInitializationIfNeeded(&m_thisRegister, &m_calleeRegister, m_scopeNode->position(), m_scopeNode->position(), m_scopeNode->position()); >+ } > } else if (constructorKind() != ConstructorKind::None) > emitThrowTypeError("Cannot call a class constructor without |new|"); > else { >@@ -873,6 +884,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, EvalNode* evalNode, UnlinkedEvalCod > > m_codeBlock->setNumParameters(1); > >+ pushPrivateAccessNames(*parentScopeTDZVariables); > pushTDZVariables(*parentScopeTDZVariables, TDZCheckOptimization::DoNotOptimize, TDZRequirement::UnderTDZ); > > emitEnter(); >@@ -1949,7 +1961,7 @@ bool BytecodeGenerator::instantiateLexicalVariables(const VariableEnvironment& l > if (lexicalVariables.privateNamesSize()) { > for (const auto& privateName : lexicalVariables.privateNames()) { > if (privateName.value.isDeclared()) >- symbolTable->addPrivateName(privateName.key.get()); >+ symbolTable->addPrivateName(privateName.key, privateName.value); > } > > hasCapturedVariables = true; >@@ -2779,6 +2791,11 @@ void BytecodeGenerator::emitPrivateFieldAdd(RegisterID* base, const Identifier& > OpAddPrivateField::emit(this, base, addConstant(name), value, scopeRegister()); > } > >+void BytecodeGenerator::emitCheckPrivateBrand(RegisterID* base, RegisterID* brand) >+{ >+ OpCheckPrivateBrand::emit(this, base, brand); >+} >+ > RegisterID* BytecodeGenerator::emitPrivateFieldGet(RegisterID* dst, RegisterID* base, const Identifier& name) > { > m_codeBlock->addPropertyAccessInstruction(instructions().size()); >@@ -2786,6 +2803,29 @@ RegisterID* BytecodeGenerator::emitPrivateFieldGet(RegisterID* dst, RegisterID* > return dst; > } > >+void BytecodeGenerator::emitCreatePrivateBrand(RegisterID* scope, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd) >+{ >+ auto symbolVar = variable(propertyNames().builtinNames().createPrivateSymbolPrivateName()); >+ >+ RegisterID* symbolScope = newTemporary(); >+ symbolScope = emitResolveScope(symbolScope, symbolVar); >+ RefPtr<RegisterID> symbolFunction = emitGetFromScope(newTemporary(), symbolScope, symbolVar, ThrowIfNotFound); >+ >+ CallArguments args(*this, nullptr); >+ emitLoad(args.thisRegister(), jsUndefined()); >+ RefPtr<RegisterID> newSymbol = emitCall(newTemporary(), symbolFunction.get(), NoExpectedFunction, args, divot, divotStart, divotEnd, DebuggableCall::No); >+ >+ Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName()); >+ >+ emitPutToScope(scope, privateBrandVar, newSymbol.get(), DoNotThrowIfNotFound, InitializationMode::Initialization); >+} >+ >+RegisterID* BytecodeGenerator::emitGetPrivateBrand(RegisterID* dst, RegisterID* scope) >+{ >+ Variable privateBrandVar = variable(propertyNames().builtinNames().privateBrandPrivateName()); >+ return emitGetFromScope(dst, scope, privateBrandVar, ThrowIfNotFound); >+} >+ > RegisterID* BytecodeGenerator::emitPrivateFieldSet(RegisterID* base, const Identifier& name, RegisterID* value) > { > m_codeBlock->addPropertyAccessInstruction(instructions().size()); >@@ -2888,6 +2928,38 @@ void BytecodeGenerator::liftTDZCheckIfPossible(const Variable& variable) > } > } > >+bool BytecodeGenerator::isPrivateMethod(const Identifier& ident) >+{ >+ for (unsigned i = m_privateNamesStack.size(); i--; ) { >+ auto& map = m_privateNamesStack[i]; >+ auto it = map.find(ident.impl()); >+ if (it != map.end()) >+ return it->value.isMethod(); >+ } >+ >+ return false; >+} >+ >+void BytecodeGenerator::pushPrivateAccessNames(const VariableEnvironment& environment) >+{ >+ if (!environment.privateNamesSize()) >+ return; >+ >+ VariableEnvironment::PrivateNames privateNamesMap; >+ for (const auto& entry : environment.privateNames()) >+ privateNamesMap.add(entry.key, entry.value); >+ >+ m_privateNamesStack.append(WTFMove(privateNamesMap)); >+} >+ >+void BytecodeGenerator::popPrivateAccessNames() >+{ >+ if (!m_privateNamesStack.size()) >+ return; >+ >+ m_privateNamesStack.removeLast(); >+} >+ > void BytecodeGenerator::pushTDZVariables(const VariableEnvironment& environment, TDZCheckOptimization optimization, TDZRequirement requirement) > { > if (!environment.size()) >@@ -2910,6 +2982,24 @@ void BytecodeGenerator::pushTDZVariables(const VariableEnvironment& environment, > m_cachedVariablesUnderTDZ = { }; > } > >+void BytecodeGenerator::getAvailablePrivateAccessNames(VariableEnvironment& result) >+{ >+ SmallPtrSet<UniquedStringImpl*, 16> excludedNames; >+ for (unsigned i = m_privateNamesStack.size(); i--; ) { >+ auto& map = m_privateNamesStack[i]; >+ for (auto& entry : map) { >+ if (entry.value.isPrivateAccess()) { >+ if (!excludedNames.contains(entry.key.get())) { >+ auto addResult = result.addPrivateName(entry.key); >+ addResult.iterator->value = entry.value; >+ excludedNames.add(entry.key.get()); >+ } >+ } else >+ excludedNames.add(entry.key.get()); >+ } >+ } >+} >+ > Optional<CompactVariableMap::Handle> BytecodeGenerator::getVariablesUnderTDZ() > { > if (m_cachedVariablesUnderTDZ) { >@@ -2943,6 +3033,8 @@ Optional<CompactVariableMap::Handle> BytecodeGenerator::getVariablesUnderTDZ() > } > } > >+ getAvailablePrivateAccessNames(environment); >+ > m_cachedVariablesUnderTDZ = m_vm->m_compactVariableMap->get(environment); > m_hasCachedVariablesUnderTDZ = !environment.isEmpty(); > if (!m_hasCachedVariablesUnderTDZ) >@@ -3124,9 +3216,9 @@ RegisterID* BytecodeGenerator::emitNewMethodDefinition(RegisterID* dst, MethodDe > } > > RegisterID* BytecodeGenerator::emitNewDefaultConstructor(RegisterID* dst, ConstructorKind constructorKind, const Identifier& name, >- const Identifier& ecmaName, const SourceCode& classSource) >+ const Identifier& ecmaName, const SourceCode& classSource, PrivateBrandRequirement privateBrandRequirement) > { >- UnlinkedFunctionExecutable* executable = m_vm->builtinExecutables()->createDefaultConstructor(constructorKind, name); >+ UnlinkedFunctionExecutable* executable = m_vm->builtinExecutables()->createDefaultConstructor(constructorKind, name, privateBrandRequirement); > executable->setInvalidTypeProfilingOffsets(); > executable->setEcmaName(ecmaName); > executable->setClassSource(classSource); >diff --git a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >index 91a6f544e85..fba6d2320d5 100644 >--- a/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >+++ b/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h >@@ -389,6 +389,7 @@ namespace JSC { > bool needsToUpdateArrowFunctionContext() const { return m_needsToUpdateArrowFunctionContext; } > bool usesEval() const { return m_scopeNode->usesEval(); } > bool usesThis() const { return m_scopeNode->usesThis(); } >+ PrivateBrandRequirement privateBrandRequirement() const { return m_codeBlock->privateBrandRequirement(); } > ConstructorKind constructorKind() const { return m_codeBlock->constructorKind(); } > SuperBinding superBinding() const { return m_codeBlock->superBinding(); } > JSParserScriptMode scriptMode() const { return m_codeBlock->scriptMode(); } >@@ -736,7 +737,7 @@ namespace JSC { > > RegisterID* emitNewFunction(RegisterID* dst, FunctionMetadataNode*); > RegisterID* emitNewFunctionExpression(RegisterID* dst, FuncExprNode*); >- RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource); >+ RegisterID* emitNewDefaultConstructor(RegisterID* dst, ConstructorKind, const Identifier& name, const Identifier& ecmaName, const SourceCode& classSource, PrivateBrandRequirement privateBrandRequirement); > RegisterID* emitNewInstanceFieldInitializerFunction(RegisterID* dst, Vector<JSTextPosition>&& instanceFieldLocations, bool isDerived); > RegisterID* emitNewArrowFunctionExpression(RegisterID*, ArrowFuncExprNode*); > RegisterID* emitNewMethodDefinition(RegisterID* dst, MethodDefinitionNode*); >@@ -782,6 +783,10 @@ namespace JSC { > RegisterID* emitPrivateFieldGet(RegisterID* dst, RegisterID* base, const Identifier& name); > RegisterID* emitPrivateFieldSet(RegisterID* base, const Identifier& name, RegisterID* value); > >+ void emitCreatePrivateBrand(RegisterID* dst, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd); >+ RegisterID* emitGetPrivateBrand(RegisterID* dst, RegisterID* scope); >+ void emitCheckPrivateBrand(RegisterID* base, RegisterID* brand); >+ > void emitSuperSamplerBegin(); > void emitSuperSamplerEnd(); > >@@ -1136,10 +1141,11 @@ namespace JSC { > if (parseMode == SourceParseMode::MethodMode && metadata->constructorKind() != ConstructorKind::None) > constructAbility = ConstructAbility::CanConstruct; > >- return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(optionalVariablesUnderTDZ), newDerivedContextType); >+ return UnlinkedFunctionExecutable::create(m_vm, m_scopeNode->source(), metadata, isBuiltinFunction() ? UnlinkedBuiltinFunction : UnlinkedNormalFunction, constructAbility, scriptMode(), WTFMove(optionalVariablesUnderTDZ), newDerivedContextType, metadata->privateBrandRequirement()); > } > > Optional<CompactVariableMap::Handle> getVariablesUnderTDZ(); >+ void getAvailablePrivateAccessNames(VariableEnvironment&); > > RegisterID* emitConstructVarargs(RegisterID* dst, RegisterID* func, RegisterID* thisRegister, RegisterID* arguments, RegisterID* firstFreeRegister, int32_t firstVarArgOffset, const JSTextPosition& divot, const JSTextPosition& divotStart, const JSTextPosition& divotEnd, DebuggableCall); > template<typename CallOp> >@@ -1197,6 +1203,11 @@ namespace JSC { > m_lastInstruction = prevLastInstruction; > } > >+ bool isPrivateMethod(const Identifier&); >+ >+ void pushPrivateAccessNames(const VariableEnvironment&); >+ void popPrivateAccessNames(); >+ > private: > InstructionStreamWriter m_writer; > >@@ -1211,6 +1222,7 @@ namespace JSC { > Vector<LexicalScopeStackEntry> m_lexicalScopeStack; > > Vector<TDZMap> m_TDZStack; >+ Vector<VariableEnvironment::PrivateNames> m_privateNamesStack; > Optional<size_t> m_varScopeLexicalScopeStackIndex; > void pushTDZVariables(const VariableEnvironment&, TDZCheckOptimization, TDZRequirement); > >diff --git a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >index 74b0d3ef01f..e79f348d681 100644 >--- a/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >+++ b/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp >@@ -706,6 +706,13 @@ void PropertyListNode::emitPutConstantProperty(BytecodeGenerator& generator, Reg > > if (node.isClassProperty()) { > ASSERT(node.needsSuperBinding()); >+ >+ if (node.type() & PropertyNode::PrivateMethod) { >+ Variable var = generator.variable(*node.name()); >+ generator.emitPutToScope(generator.scopeRegister(), var, value.get(), DoNotThrowIfNotFound, InitializationMode::ConstInitialization); >+ return; >+ } >+ > RefPtr<RegisterID> propertyNameRegister; > if (node.name()) > propertyNameRegister = generator.emitLoad(nullptr, *node.name()); >@@ -811,8 +818,19 @@ RegisterID* DotAccessorNode::emitBytecode(BytecodeGenerator& generator, Register > > RegisterID* BaseDotNode::emitGetPropertyValue(BytecodeGenerator& generator, RegisterID* dst, RegisterID* base, RefPtr<RegisterID>& thisValue) > { >- if (isPrivateName()) >+ if (isPrivateName()) { >+ if (generator.isPrivateMethod(identifier())) { >+ Variable var = generator.variable(identifier()); >+ RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); >+ >+ RegisterID* privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get()); >+ generator.emitCheckPrivateBrand(base, privateBrandSymbol); >+ >+ return generator.emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound); >+ } >+ > return generator.emitPrivateFieldGet(dst, base, identifier()); >+ } > > if (m_base->isSuperNode()) { > if (!thisValue) >@@ -831,8 +849,20 @@ RegisterID* BaseDotNode::emitGetPropertyValue(BytecodeGenerator& generator, Regi > > RegisterID* BaseDotNode::emitPutProperty(BytecodeGenerator& generator, RegisterID* base, RegisterID* value, RefPtr<RegisterID>& thisValue) > { >- if (isPrivateName()) >+ if (isPrivateName()) { >+ auto identifierName = identifier(); >+ if (generator.isPrivateMethod(identifierName)) { >+ Variable var = generator.variable(identifierName); >+ RefPtr<RegisterID> scope = generator.emitResolveScope(nullptr, var); >+ >+ RegisterID* privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), scope.get()); >+ generator.emitCheckPrivateBrand(base, privateBrandSymbol); >+ >+ generator.emitThrowTypeError("Trying to access a not defined private setter"); >+ } >+ > return generator.emitPrivateFieldSet(base, m_ident, value); >+ } > > if (m_base->isSuperNode()) { > if (!thisValue) >@@ -971,10 +1001,16 @@ RegisterID* FunctionCallValueNode::emitBytecode(BytecodeGenerator& generator, Re > > // Initialize instance fields after super-call. > if (Options::useClassFields()) { >+ if (generator.privateBrandRequirement() == PrivateBrandRequirement::Needed) { >+ // FIXME: turn this a method of BytecodeGenerator. It is the same as Base constructor >+ Variable privateBrandVar = generator.variable(generator.propertyNames().builtinNames().privateBrandPrivateName()); >+ RefPtr<RegisterID> privateBrandVarScope = generator.emitResolveScope(nullptr, privateBrandVar); >+ RegisterID* privateBrandSymbol = generator.emitGetPrivateBrand(generator.newTemporary(), privateBrandVarScope.get()); >+ generator.emitDirectPutByVal(generator.thisRegister(), privateBrandSymbol, privateBrandSymbol); >+ } > func = generator.emitLoadDerivedConstructor(); > generator.emitInstanceFieldInitializationIfNeeded(generator.thisRegister(), func.get(), divot(), divotStart(), divotEnd()); > } >- > return ret; > } > RefPtr<RegisterID> func = generator.emitNode(m_expr); >@@ -4079,6 +4115,13 @@ RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID > if (m_needsLexicalScope) > generator.pushLexicalScope(this, BytecodeGenerator::TDZCheckOptimization::Optimize, BytecodeGenerator::NestedScopeType::IsNested); > >+ bool hasPrivateNames = !!m_lexicalVariables.privateNamesSize(); >+ bool shouldEmitPrivateBrand = m_lexicalVariables.hasPrivateAccess(); >+ if (hasPrivateNames) >+ generator.pushPrivateAccessNames(m_lexicalVariables); >+ if (shouldEmitPrivateBrand) >+ generator.emitCreatePrivateBrand(generator.scopeRegister(), m_position, m_position, m_position); >+ > RefPtr<RegisterID> superclass; > if (m_classHeritage) { > superclass = generator.newTemporary(); >@@ -4088,15 +4131,18 @@ RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID > RefPtr<RegisterID> constructor; > bool needsHomeObject = false; > >+ >+ PrivateBrandRequirement privateBrandRequirement = shouldEmitPrivateBrand ? PrivateBrandRequirement::Needed : PrivateBrandRequirement::None; > if (m_constructorExpression) { > ASSERT(m_constructorExpression->isFuncExprNode()); > FunctionMetadataNode* metadata = static_cast<FuncExprNode*>(m_constructorExpression)->metadata(); > metadata->setEcmaName(ecmaName()); > metadata->setClassSource(m_classSource); >+ metadata->setPrivateBrandRequirement(privateBrandRequirement); > constructor = generator.emitNode(dst, m_constructorExpression); > needsHomeObject = m_classHeritage || metadata->superBinding() == SuperBinding::Needed; > } else >- constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource); >+ constructor = generator.emitNewDefaultConstructor(generator.finalDestination(dst), m_classHeritage ? ConstructorKind::Extends : ConstructorKind::Base, m_name, ecmaName(), m_classSource, privateBrandRequirement); > > const auto& propertyNames = generator.propertyNames(); > RefPtr<RegisterID> prototype = generator.emitNewObject(generator.newTemporary()); >@@ -4166,6 +4212,9 @@ RegisterID* ClassExprNode::emitBytecode(BytecodeGenerator& generator, RegisterID > generator.popLexicalScope(this); > } > >+ if (hasPrivateNames) >+ generator.popPrivateAccessNames(); >+ > return generator.move(dst, constructor.get()); > } > >diff --git a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >index a68281e4c0d..e2ec248f837 100644 >--- a/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >+++ b/Source/JavaScriptCore/dfg/DFGCapabilities.cpp >@@ -284,6 +284,7 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, const I > case op_add_private_field: // FIXME: add JIT support for private field ops. https://bugs.webkit.org/show_bug.cgi?id=195619 > case op_get_private_field: > case op_put_private_field: >+ case op_check_private_brand: > case op_to_property_key: > case llint_program_prologue: > case llint_eval_prologue: >diff --git a/Source/JavaScriptCore/jit/JIT.cpp b/Source/JavaScriptCore/jit/JIT.cpp >index 35cdeb1d29c..57d6ce0c863 100644 >--- a/Source/JavaScriptCore/jit/JIT.cpp >+++ b/Source/JavaScriptCore/jit/JIT.cpp >@@ -423,6 +423,7 @@ void JIT::privateCompileMainPass() > DEFINE_OP(op_add_private_field) > DEFINE_OP(op_put_private_field) > DEFINE_OP(op_to_property_key) >+ DEFINE_OP(op_check_private_brand) > > DEFINE_OP(op_ret) > DEFINE_OP(op_rshift) >@@ -592,6 +593,7 @@ void JIT::privateCompileSlowCases() > DEFINE_SLOWCASE_SLOW_OP(get_private_field) > DEFINE_SLOWCASE_SLOW_OP(put_private_field) > DEFINE_SLOWCASE_SLOW_OP(to_property_key) >+ DEFINE_SLOWCASE_SLOW_OP(check_private_brand) > > default: > RELEASE_ASSERT_NOT_REACHED(); >diff --git a/Source/JavaScriptCore/jit/JIT.h b/Source/JavaScriptCore/jit/JIT.h >index ddffdac1a1c..de88a0ef0c1 100644 >--- a/Source/JavaScriptCore/jit/JIT.h >+++ b/Source/JavaScriptCore/jit/JIT.h >@@ -638,6 +638,7 @@ namespace JSC { > void emit_op_get_private_field(const Instruction*); > void emit_op_put_private_field(const Instruction*); > void emit_op_to_property_key(const Instruction*); >+ void emit_op_check_private_brand(const Instruction*); > > void emitSlow_op_add(const Instruction*, Vector<SlowCaseEntry>::iterator&); > void emitSlow_op_call(const Instruction*, Vector<SlowCaseEntry>::iterator&); >diff --git a/Source/JavaScriptCore/jit/JITOpcodes.cpp b/Source/JavaScriptCore/jit/JITOpcodes.cpp >index 9a2979168a7..1cb12b3314a 100644 >--- a/Source/JavaScriptCore/jit/JITOpcodes.cpp >+++ b/Source/JavaScriptCore/jit/JITOpcodes.cpp >@@ -1582,6 +1582,10 @@ void JIT::emit_op_to_property_key(const Instruction*) > { > addSlowCase(jump()); > } >+void JIT::emit_op_check_private_brand(const Instruction*) >+{ >+ addSlowCase(jump()); >+} > > } // namespace JSC > >diff --git a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >index 5086d8422b4..2d53d68f2fb 100644 >--- a/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >+++ b/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm >@@ -1568,7 +1568,6 @@ llintOpWithMetadata(op_get_by_val, OpGetByVal, macro (size, get, dispatch, metad > dispatch() > end) > >- > macro putByValOp(opcodeName, opcodeStruct) > llintOpWithMetadata(op_%opcodeName%, opcodeStruct, macro (size, get, dispatch, metadata, return) > macro contiguousPutByVal(storeCallback) >@@ -2598,6 +2597,10 @@ llintOpWithMetadata(op_add_private_field, OpAddPrivateField, macro (size, get, d > dispatch() > end) > >+llintOp(op_check_private_brand, OpCheckPrivateBrand, macro (size, get, dispatch) >+ callSlowPath(_slow_path_check_private_brand) >+ dispatch() >+end) > > llintOpWithMetadata(op_get_private_field, OpGetPrivateField, macro (size, get, dispatch, metadata, return) > get(m_base, t0) >diff --git a/Source/JavaScriptCore/parser/ASTBuilder.h b/Source/JavaScriptCore/parser/ASTBuilder.h >index 65e04fc1ebb..e26af02bad5 100644 >--- a/Source/JavaScriptCore/parser/ASTBuilder.h >+++ b/Source/JavaScriptCore/parser/ASTBuilder.h >@@ -1390,6 +1390,7 @@ ExpressionNode* ASTBuilder::makeFunctionCallNode(const JSTokenLocation& location > } > if (!node) > node = new (m_parserArena) FunctionCallDotNode(location, dot->base(), dot->identifier(), dot->type(), args, divot, divotStart, divotEnd); >+ > node->setSubexpressionInfo(dot->divot(), dot->divotEnd().offset); > return node; > } >diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp >index 615e29a5d63..7234a473488 100644 >--- a/Source/JavaScriptCore/parser/Lexer.cpp >+++ b/Source/JavaScriptCore/parser/Lexer.cpp >@@ -1059,20 +1059,21 @@ template <bool shouldCreateIdentifier> ALWAYS_INLINE JSTokenType Lexer<UChar>::p > } else > tokenData->ident = nullptr; > >+ auto identType = isPrivateName ? PRIVATENAME : IDENT; > if (UNLIKELY((remaining < maxTokenLength) && !(lexerFlags & LexerFlagsIgnoreReservedWords)) && !isPrivateIdentifier) { > ASSERT(shouldCreateIdentifier); > if (remaining < maxTokenLength) { > const HashTableValue* entry = JSC::mainTable.entry(*ident); > ASSERT((remaining < maxTokenLength) || !entry); > if (!entry) >- return IDENT; >+ return identType; > JSTokenType token = static_cast<JSTokenType>(entry->lexerValue()); >- return (token != RESERVED_IF_STRICT) || strictMode ? token : IDENT; >+ return (token != RESERVED_IF_STRICT) || strictMode ? token : identType; > } >- return IDENT; >+ return identType; > } > >- return IDENT; >+ return identType; > } > > template<typename CharacterType> template<bool shouldCreateIdentifier> JSTokenType Lexer<CharacterType>::parseIdentifierSlowCase(JSTokenData* tokenData, unsigned lexerFlags, bool strictMode) >diff --git a/Source/JavaScriptCore/parser/NodeConstructors.h b/Source/JavaScriptCore/parser/NodeConstructors.h >index f86e1a6d292..fb5224f77b8 100644 >--- a/Source/JavaScriptCore/parser/NodeConstructors.h >+++ b/Source/JavaScriptCore/parser/NodeConstructors.h >@@ -253,7 +253,7 @@ namespace JSC { > , m_type(type) > , m_needsSuperBinding(superBinding == SuperBinding::Needed) > , m_putType(putType) >- , m_isPrivate(!!(type & Private)) >+ , m_isPrivate(!!(type & (PrivateField | PrivateMethod))) > , m_classElementTag(static_cast<unsigned>(tag)) > , m_isOverriddenByDuplicate(false) > { >@@ -266,7 +266,7 @@ namespace JSC { > , m_type(type) > , m_needsSuperBinding(superBinding == SuperBinding::Needed) > , m_putType(putType) >- , m_isPrivate(!!(type & Private)) >+ , m_isPrivate(!!(type & (PrivateField | PrivateMethod))) > , m_classElementTag(static_cast<unsigned>(tag)) > , m_isOverriddenByDuplicate(false) > { >@@ -279,7 +279,7 @@ namespace JSC { > , m_type(type) > , m_needsSuperBinding(superBinding == SuperBinding::Needed) > , m_putType(putType) >- , m_isPrivate(!!(type & Private)) >+ , m_isPrivate(!!(type & (PrivateField | PrivateMethod))) > , m_classElementTag(static_cast<unsigned>(tag)) > , m_isOverriddenByDuplicate(false) > { >@@ -292,7 +292,7 @@ namespace JSC { > , m_type(type) > , m_needsSuperBinding(superBinding == SuperBinding::Needed) > , m_putType(putType) >- , m_isPrivate(!!(type & Private)) >+ , m_isPrivate(!!(type & (PrivateField | PrivateMethod))) > , m_classElementTag(static_cast<unsigned>(tag)) > , m_isOverriddenByDuplicate(false) > { >diff --git a/Source/JavaScriptCore/parser/Nodes.h b/Source/JavaScriptCore/parser/Nodes.h >index 1df9c619158..531b7de12ff 100644 >--- a/Source/JavaScriptCore/parser/Nodes.h >+++ b/Source/JavaScriptCore/parser/Nodes.h >@@ -706,7 +706,7 @@ namespace JSC { > enum class ClassElementTag : uint8_t { No, Instance, Static, LastTag }; > class PropertyNode final : public ParserArenaFreeable { > public: >- enum Type : uint8_t { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16, Spread = 32, Private = 64 }; >+ enum Type : uint8_t { Constant = 1, Getter = 2, Setter = 4, Computed = 8, Shorthand = 16, Spread = 32, PrivateField = 64, PrivateMethod = 128 }; > enum PutType : uint8_t { Unknown, KnownDirect }; > > PropertyNode(const Identifier&, ExpressionNode*, Type, PutType, SuperBinding, ClassElementTag); >@@ -736,7 +736,7 @@ namespace JSC { > const Identifier* m_name; > ExpressionNode* m_expression; > ExpressionNode* m_assign; >- unsigned m_type : 7; >+ unsigned m_type; > unsigned m_needsSuperBinding : 1; > unsigned m_putType : 1; > unsigned m_isPrivate : 1; >@@ -2030,6 +2030,9 @@ namespace JSC { > void setInferredName(const Identifier& inferredName) { ASSERT(!inferredName.isNull()); m_inferredName = inferredName; } > const Identifier& inferredName() { return m_inferredName.isEmpty() ? m_ident : m_inferredName; } > >+ void setPrivateBrandRequirement(PrivateBrandRequirement privateBrandRequirement) { m_privateBrandRequirement = static_cast<unsigned>(privateBrandRequirement); } >+ PrivateBrandRequirement privateBrandRequirement() { return static_cast<PrivateBrandRequirement>(m_privateBrandRequirement); } >+ > FunctionMode functionMode() { return m_functionMode; } > > int functionNameStart() const { return m_functionNameStart; } >@@ -2071,6 +2074,7 @@ namespace JSC { > unsigned m_superBinding : 1; > unsigned m_constructorKind : 2; > unsigned m_isArrowFunctionBodyExpression : 1; >+ unsigned m_privateBrandRequirement : 1; > SourceParseMode m_parseMode; > FunctionMode m_functionMode; > Identifier m_ident; >diff --git a/Source/JavaScriptCore/parser/Parser.cpp b/Source/JavaScriptCore/parser/Parser.cpp >index 9f7ab279e25..71944385f46 100644 >--- a/Source/JavaScriptCore/parser/Parser.cpp >+++ b/Source/JavaScriptCore/parser/Parser.cpp >@@ -2936,15 +2936,19 @@ parseMethod: > break; > case PRIVATENAME: { > ASSERT(Options::useClassFields()); >- JSToken token = m_token; > ident = m_token.m_data.ident; > failIfTrue(tag == ClassElementTag::Static, "Static class element cannot be private"); > failIfTrue(isGetter || isSetter, "Cannot parse class method with private name"); > ASSERT(ident); > next(); >- failIfTrue(matchAndUpdate(OPENPAREN, token), "Cannot parse class method with private name"); >+ if (Options::usePrivateMethods() && match(OPENPAREN)) { >+ semanticFailIfTrue(classScope->declarePrivateMethod(*ident) & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare private method twice"); >+ type = static_cast<PropertyNode::Type>(type | PropertyNode::PrivateMethod); >+ break; >+ } else >+ failIfTrue(match(OPENPAREN), "Cannot parse class method with private name"); > semanticFailIfTrue(classScope->declarePrivateName(*ident) & DeclarationResult::InvalidDuplicateDeclaration, "Cannot declare private field twice"); >- type = static_cast<PropertyNode::Type>(type | PropertyNode::Private); >+ type = static_cast<PropertyNode::Type>(type | PropertyNode::PrivateField); > break; > } > default: >diff --git a/Source/JavaScriptCore/parser/Parser.h b/Source/JavaScriptCore/parser/Parser.h >index 10c7fbeb6b9..17692b39880 100644 >--- a/Source/JavaScriptCore/parser/Parser.h >+++ b/Source/JavaScriptCore/parser/Parser.h >@@ -498,6 +498,27 @@ public: > m_lexicalVariables.usePrivateName(ident); > } > >+ DeclarationResultMask declarePrivateMethod(const Identifier& ident) >+ { >+ ASSERT(m_allowsLexicalDeclarations); >+ DeclarationResultMask result = DeclarationResult::Valid; >+ bool addResult = m_lexicalVariables.declarePrivateMethod(ident); >+ >+ if (!addResult) { >+ result |= DeclarationResult::InvalidDuplicateDeclaration; >+ return result; >+ } >+ >+ // We declare it since we store private methods on class >+ // scope. >+ DeclarationResultMask declarationResult = declareLexicalVariable(&ident, false); >+ ASSERT_UNUSED(declarationResult, declarationResult == DeclarationResult::Valid); >+ useVariable(&ident, false); >+ addClosedVariableCandidateUnconditionally(ident.impl()); >+ >+ return result; >+ } >+ > DeclarationResultMask declarePrivateName(const Identifier& ident) > { > ASSERT(m_allowsLexicalDeclarations); >diff --git a/Source/JavaScriptCore/parser/ParserModes.h b/Source/JavaScriptCore/parser/ParserModes.h >index 5d5882c7571..391d8090f07 100644 >--- a/Source/JavaScriptCore/parser/ParserModes.h >+++ b/Source/JavaScriptCore/parser/ParserModes.h >@@ -37,6 +37,8 @@ enum class JSParserScriptMode { Classic, Module }; > enum class ConstructorKind { None, Base, Extends }; > enum class SuperBinding { Needed, NotNeeded }; > >+enum class PrivateBrandRequirement { None, Needed }; >+ > enum class CodeGenerationMode : uint8_t { > Debugger = 1 << 0, > TypeProfiler = 1 << 1, >diff --git a/Source/JavaScriptCore/parser/VariableEnvironment.cpp b/Source/JavaScriptCore/parser/VariableEnvironment.cpp >index e32e9263df2..300caceebdf 100644 >--- a/Source/JavaScriptCore/parser/VariableEnvironment.cpp >+++ b/Source/JavaScriptCore/parser/VariableEnvironment.cpp >@@ -107,6 +107,40 @@ void VariableEnvironment::markVariableAsExported(const RefPtr<UniquedStringImpl> > findResult->value.setIsExported(); > } > >+void VariableEnvironment::markPrivateNameAsDeclared(const Identifier& identifier) >+{ >+ if (!m_rareData) >+ return; >+ auto findResult = m_rareData->m_privateNames.find(identifier.impl()); >+ RELEASE_ASSERT(findResult != m_rareData->m_privateNames.end()); >+ findResult->value.setIsDeclared(); >+} >+ >+// FIXME: The code is the same of declarePrivateName. Refactor this. >+bool VariableEnvironment::declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier) >+{ >+ if (!m_rareData) >+ m_rareData = std::make_unique<VariableEnvironmentRareData>(); >+ >+ auto findResult = m_rareData->m_privateNames.find(identifier); >+ >+ if (findResult == m_rareData->m_privateNames.end()) { >+ PrivateNameEntry entry(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsMethod); >+ >+ auto addResult = m_rareData->m_privateNames.add(identifier, entry); >+ return addResult.isNewEntry; >+ } >+ >+ >+ if (findResult->value.isDeclared()) >+ return false; // Error: declaring a duplicate private name. >+ >+ // it was previously used, mark it as declared. >+ PrivateNameEntry entry(PrivateNameEntry::Traits::IsDeclared | PrivateNameEntry::Traits::IsUsed | PrivateNameEntry::Traits::IsMethod); >+ auto addResult = m_rareData->m_privateNames.set(identifier, entry); >+ return !addResult.isNewEntry; >+} >+ > bool VariableEnvironment::declarePrivateName(const RefPtr<UniquedStringImpl>& identifier) > { > if (!m_rareData) >@@ -159,6 +193,25 @@ CompactVariableEnvironment::CompactVariableEnvironment(const VariableEnvironment > }); > > m_hash = 0; >+ if (env.privateNamesSize()) { >+ Vector<std::pair<UniquedStringImpl*, PrivateNameEntry>, 16> sortedPrivateEntries; >+ sortedPrivateEntries.reserveInitialCapacity(env.privateNamesSize()); >+ for (const auto& entries : env.privateNames()) >+ sortedPrivateEntries.append({entries.key.get(), entries.value}); >+ >+ std::sort(sortedPrivateEntries.begin(), sortedPrivateEntries.end(), [] (const auto& a, const auto& b) { >+ return a.first < b.first; >+ }); >+ >+ m_privateAccessNames.reserveInitialCapacity(env.privateNamesSize()); >+ for (const auto& pair : sortedPrivateEntries) { >+ m_privateAccessNames.append(pair.first); >+ m_privateNameMetadata.append(pair.second); >+ m_hash ^= pair.first->hash(); >+ m_hash += pair.second.bits(); >+ } >+ } >+ > m_variables.reserveInitialCapacity(sortedEntries.size()); > m_variableMetadata.reserveInitialCapacity(sortedEntries.size()); > for (const auto& pair : sortedEntries) { >@@ -182,6 +235,10 @@ bool CompactVariableEnvironment::operator==(const CompactVariableEnvironment& ot > return false; > if (m_variableMetadata != other.m_variableMetadata) > return false; >+ if (m_privateAccessNames != other.m_privateAccessNames) >+ return false; >+ if (m_privateNameMetadata != other.m_privateNameMetadata) >+ return false; > return true; > } > >@@ -195,6 +252,12 @@ VariableEnvironment CompactVariableEnvironment::toVariableEnvironment() const > addResult.iterator->value = m_variableMetadata[i]; > } > >+ for (size_t i = 0; i < m_privateAccessNames.size(); i++) { >+ auto addResult = result.addPrivateName(m_privateAccessNames[i]); >+ ASSERT(addResult.isNewEntry); >+ addResult.iterator->value = m_privateNameMetadata[i]; >+ } >+ > if (m_isEverythingCaptured) > result.markAllVariablesAsCaptured(); > >diff --git a/Source/JavaScriptCore/parser/VariableEnvironment.h b/Source/JavaScriptCore/parser/VariableEnvironment.h >index 58f1a0b5623..5385ee0a258 100644 >--- a/Source/JavaScriptCore/parser/VariableEnvironment.h >+++ b/Source/JavaScriptCore/parser/VariableEnvironment.h >@@ -86,11 +86,16 @@ struct VariableEnvironmentEntryHashTraits : HashTraits<VariableEnvironmentEntry> > }; > > struct PrivateNameEntry { >+ friend class CachedPrivateNameEntry; >+ > public: > PrivateNameEntry(uint16_t traits = 0) { m_bits = traits; } > > ALWAYS_INLINE bool isUsed() const { return m_bits & IsUsed; } > ALWAYS_INLINE bool isDeclared() const { return m_bits & IsDeclared; } >+ ALWAYS_INLINE bool isMethod() const { return m_bits & IsMethod; } >+ >+ bool isPrivateAccess() const { return isMethod(); } > > ALWAYS_INLINE void setIsUsed() { m_bits |= IsUsed; } > ALWAYS_INLINE void setIsDeclared() { m_bits |= IsDeclared; } >@@ -105,6 +110,7 @@ public: > enum Traits : uint16_t { > IsUsed = 1 << 0, > IsDeclared = 1 << 1, >+ IsMethod = 1 << 2, > }; > > private: >@@ -118,8 +124,10 @@ struct PrivateNameEntryHashTraits : HashTraits<PrivateNameEntry> { > class VariableEnvironment { > private: > typedef HashMap<RefPtr<UniquedStringImpl>, VariableEnvironmentEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, VariableEnvironmentEntryHashTraits> Map; >- typedef HashMap<RefPtr<UniquedStringImpl>, PrivateNameEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, PrivateNameEntryHashTraits> PrivateNames; >+ > public: >+ typedef HashMap<RefPtr<UniquedStringImpl>, PrivateNameEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, PrivateNameEntryHashTraits> PrivateNames; >+ > VariableEnvironment() > { } > VariableEnvironment(VariableEnvironment&& other) >@@ -140,6 +148,16 @@ public: > ALWAYS_INLINE Map::const_iterator end() const { return m_map.end(); } > ALWAYS_INLINE Map::AddResult add(const RefPtr<UniquedStringImpl>& identifier) { return m_map.add(identifier, VariableEnvironmentEntry()); } > ALWAYS_INLINE Map::AddResult add(const Identifier& identifier) { return add(identifier.impl()); } >+ >+ ALWAYS_INLINE PrivateNames::AddResult addPrivateName(const Identifier& identifier) { return addPrivateName(identifier.impl()); } >+ ALWAYS_INLINE PrivateNames::AddResult addPrivateName(const RefPtr<UniquedStringImpl>& identifier) >+ { >+ if (!m_rareData) >+ m_rareData = std::make_unique<VariableEnvironmentRareData>(); >+ >+ return m_rareData->m_privateNames.add(identifier, PrivateNameEntry()); >+ } >+ > ALWAYS_INLINE unsigned size() const { return m_map.size() + privateNamesSize(); } > ALWAYS_INLINE unsigned mapSize() const { return m_map.size(); } > ALWAYS_INLINE bool contains(const RefPtr<UniquedStringImpl>& identifier) const { return m_map.contains(identifier); } >@@ -160,6 +178,17 @@ public: > > typedef WTF::IteratorRange<PrivateNames::iterator> PrivateNamesRange; > >+ void markPrivateNameAsDeclared(const Identifier&); >+ >+ bool declarePrivateMethod(const Identifier& identifier) { return declarePrivateMethod(identifier.impl()); } >+ bool declarePrivateMethod(const RefPtr<UniquedStringImpl>& identifier); >+ >+ bool declarePrivateSetter(const Identifier& identifier) { return declarePrivateSetter(identifier.impl()); } >+ bool declarePrivateSetter(const RefPtr<UniquedStringImpl>& identifier); >+ >+ bool declarePrivateGetter(const Identifier& identifier) { return declarePrivateGetter(identifier.impl()); } >+ bool declarePrivateGetter(const RefPtr<UniquedStringImpl>& identifier); >+ > bool declarePrivateName(const Identifier& identifier) { return declarePrivateName(identifier.impl()); } > bool declarePrivateName(const RefPtr<UniquedStringImpl>& identifier); > void usePrivateName(const RefPtr<UniquedStringImpl>& identifier); >@@ -181,6 +210,19 @@ public: > return m_rareData->m_privateNames.size(); > } > >+ ALWAYS_INLINE bool hasPrivateAccess() const >+ { >+ if (!m_rareData) >+ return false; >+ >+ for (auto entry : privateNames()) { >+ if (entry.value.isPrivateAccess()) >+ return true; >+ } >+ >+ return false; >+ } >+ > ALWAYS_INLINE bool hasPrivateName(const Identifier& identifier) > { > if (!m_rareData) >@@ -263,6 +305,9 @@ private: > > Vector<RefPtr<UniquedStringImpl>> m_variables; > Vector<VariableEnvironmentEntry> m_variableMetadata; >+ Vector<RefPtr<UniquedStringImpl>> m_privateAccessNames; >+ Vector<PrivateNameEntry> m_privateNameMetadata; >+ > unsigned m_hash; > bool m_isEverythingCaptured; > }; >diff --git a/Source/JavaScriptCore/runtime/CachedTypes.cpp b/Source/JavaScriptCore/runtime/CachedTypes.cpp >index 50aaf702f35..6a79a2d691b 100644 >--- a/Source/JavaScriptCore/runtime/CachedTypes.cpp >+++ b/Source/JavaScriptCore/runtime/CachedTypes.cpp >@@ -1059,6 +1059,22 @@ private: > intptr_t m_bits; > }; > >+class CachedPrivateNameEntry : public CachedObject<PrivateNameEntry> { >+public: >+ void encode(Encoder&, const PrivateNameEntry& privateNameEntry) >+ { >+ m_bits = privateNameEntry.m_bits; >+ } >+ >+ void decode(Decoder&, PrivateNameEntry& privateNameEntry) const >+ { >+ privateNameEntry.m_bits = m_bits; >+ } >+ >+private: >+ uint16_t m_bits; >+}; >+ > class CachedSymbolTableRareData : public CachedObject<SymbolTable::SymbolTableRareData> { > public: > void encode(Encoder& encoder, const SymbolTable::SymbolTableRareData& rareData) >@@ -1074,7 +1090,7 @@ public: > } > > private: >- CachedHashSet<CachedRefPtr<CachedUniquedStringImpl>, StringRepHash> m_privateNames; >+ CachedHashMap<CachedRefPtr<CachedUniquedStringImpl>, CachedPrivateNameEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>, PrivateNameEntryHashTraits> m_privateNames; > }; > > class CachedSymbolTable : public CachedObject<SymbolTable> { >diff --git a/Source/JavaScriptCore/runtime/CodeCache.h b/Source/JavaScriptCore/runtime/CodeCache.h >index 3768555da8c..4d331f29387 100644 >--- a/Source/JavaScriptCore/runtime/CodeCache.h >+++ b/Source/JavaScriptCore/runtime/CodeCache.h >@@ -279,7 +279,7 @@ UnlinkedCodeBlockType* generateUnlinkedCodeBlockImpl(VM& vm, const SourceCode& s > > bool usesEval = rootNode->features() & EvalFeature; > bool isStrictMode = rootNode->features() & StrictModeFeature; >- ExecutableInfo executableInfo(usesEval, isStrictMode, false, false, ConstructorKind::None, scriptMode, SuperBinding::NotNeeded, CacheTypes<UnlinkedCodeBlockType>::parseMode, derivedContextType, isArrowFunctionContext, false, evalContextType); >+ ExecutableInfo executableInfo(usesEval, isStrictMode, false, PrivateBrandRequirement::None, false, ConstructorKind::None, scriptMode, SuperBinding::NotNeeded, CacheTypes<UnlinkedCodeBlockType>::parseMode, derivedContextType, isArrowFunctionContext, false, evalContextType); > > UnlinkedCodeBlockType* unlinkedCodeBlock = UnlinkedCodeBlockType::create(&vm, executableInfo, codeGenerationMode); > unlinkedCodeBlock->recordParse(rootNode->features(), rootNode->hasCapturedVariables(), lineCount, unlinkedEndColumn); >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >index 326e7eedf1a..17d7d41fdf0 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp >@@ -1562,4 +1562,29 @@ SLOW_PATH_DECL(slow_path_put_private_field) > END(); > } > >+SLOW_PATH_DECL(slow_path_check_private_brand) >+{ >+ BEGIN(); >+ auto bytecode = pc->as<OpCheckPrivateBrand>(); >+ >+ JSValue baseValue = GET(bytecode.m_base).jsValue(); >+ if (!baseValue.isObject()) >+ THROW(createTypeError(exec, "Brand check failed")); >+ JSValue brand = GET_C(bytecode.m_brand).jsValue(); >+ ASSERT(brand.isSymbol()); >+ >+ baseValue.requireObjectCoercible(exec); >+ CHECK_EXCEPTION(); >+ auto property = brand.toPropertyKey(exec); >+ CHECK_EXCEPTION(); >+ >+ ASSERT(property.isPrivateName()); >+ PropertySlot slot(baseValue, PropertySlot::PropertySlot::InternalMethodType::VMInquiry); >+ bool found = JSObject::getOwnPropertySlot(asObject(baseValue), exec, property, slot); >+ if (!found) >+ THROW(createTypeError(exec, "Brand check failed")); >+ >+ END(); >+} >+ > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/CommonSlowPaths.h b/Source/JavaScriptCore/runtime/CommonSlowPaths.h >index 9ded7017b9c..e39a62ea0c0 100644 >--- a/Source/JavaScriptCore/runtime/CommonSlowPaths.h >+++ b/Source/JavaScriptCore/runtime/CommonSlowPaths.h >@@ -398,6 +398,7 @@ SLOW_PATH_HIDDEN_DECL(slow_path_spread); > SLOW_PATH_HIDDEN_DECL(slow_path_add_private_field); > SLOW_PATH_HIDDEN_DECL(slow_path_get_private_field); > SLOW_PATH_HIDDEN_DECL(slow_path_put_private_field); >+SLOW_PATH_HIDDEN_DECL(slow_path_check_private_brand); > > using SlowPathFunction = SlowPathReturnType(SLOW_PATH *)(ExecState*, const Instruction*); > >diff --git a/Source/JavaScriptCore/runtime/EvalExecutable.h b/Source/JavaScriptCore/runtime/EvalExecutable.h >index 57b7a35f432..dc2332d4377 100644 >--- a/Source/JavaScriptCore/runtime/EvalExecutable.h >+++ b/Source/JavaScriptCore/runtime/EvalExecutable.h >@@ -62,7 +62,7 @@ public: > > DECLARE_INFO; > >- ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, evalContextType()); } >+ ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, PrivateBrandRequirement::None, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, evalContextType()); } > > unsigned numVariables() { return m_unlinkedEvalCodeBlock->numVariables(); } > unsigned numFunctionHoistingCandidates() { return m_unlinkedEvalCodeBlock->numFunctionHoistingCandidates(); } >diff --git a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >index 64d468e83f4..c9e0dfca3df 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.cpp >@@ -264,6 +264,12 @@ static EncodedJSValue JSC_HOST_CALL hasOwnLengthProperty(ExecState* exec) > return JSValue::encode(jsBoolean(target->hasOwnProperty(exec, vm.propertyNames->length))); > } > >+static EncodedJSValue JSC_HOST_CALL createPrivateSymbol(ExecState* exec) >+{ >+ VM& vm = exec->vm(); >+ return JSValue::encode(Symbol::create(vm, PrivateSymbolImpl::createNullSymbol())); >+} >+ > #if !ASSERT_DISABLED > static EncodedJSValue JSC_HOST_CALL assertCall(ExecState* exec) > { >@@ -1020,6 +1026,9 @@ putDirectWithoutTransition(vm, vm.propertyNames-> jsName, lowerName ## Construct > GlobalPropertyInfo(vm.propertyNames->builtinNames().makeBoundFunctionPrivateName(), JSFunction::create(vm, this, 5, String(), makeBoundFunction), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().hasOwnLengthPropertyPrivateName(), JSFunction::create(vm, this, 1, String(), hasOwnLengthProperty), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), > >+ // PrivateSymbol creation >+ GlobalPropertyInfo(vm.propertyNames->builtinNames().createPrivateSymbolPrivateName(), JSFunction::create(vm, this, 0, String(), createPrivateSymbol), PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), >+ > // Map and Set helpers. > GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketHeadPrivateName(), privateFuncMapBucketHead, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), > GlobalPropertyInfo(vm.propertyNames->builtinNames().mapBucketNextPrivateName(), privateFuncMapBucketNext, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly), >diff --git a/Source/JavaScriptCore/runtime/JSScope.cpp b/Source/JavaScriptCore/runtime/JSScope.cpp >index ed2a9a2a6b0..9171dbaac3a 100644 >--- a/Source/JavaScriptCore/runtime/JSScope.cpp >+++ b/Source/JavaScriptCore/runtime/JSScope.cpp >@@ -341,8 +341,13 @@ void JSScope::collectClosureVariablesUnderTDZ(JSScope* scope, VariableEnvironmen > result.add(iter->key); > if (symbolTable->hasPrivateNames()) { > auto privateNames = symbolTable->privateNames(); >- for (auto end = privateNames.end(), iter = privateNames.begin(); iter != end; ++iter) >- result.usePrivateName(*iter); >+ for (auto end = privateNames.end(), iter = privateNames.begin(); iter != end; ++iter) { >+ if (iter->value.isPrivateAccess()) { >+ auto addResult = result.addPrivateName(iter->key); >+ addResult.iterator->value = iter->value; >+ } else >+ result.usePrivateName(iter->key); >+ } > } > } > } >diff --git a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h >index 83f233249e3..912f2128544 100644 >--- a/Source/JavaScriptCore/runtime/JSSymbolTableObject.h >+++ b/Source/JavaScriptCore/runtime/JSSymbolTableObject.h >@@ -42,7 +42,7 @@ public: > static const unsigned StructureFlags = Base::StructureFlags | OverridesGetPropertyNames; > > SymbolTable* symbolTable() const { return m_symbolTable.get(); } >- >+ > JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName); > JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode); > >@@ -82,8 +82,8 @@ protected: > m_symbolTable.set(vm, this, symbolTable); > if (symbolTable->hasPrivateNames()) { > m_rareData = std::make_unique<JSSymbolTableObjectRareData>(); >- for (auto key : symbolTable->privateNames()) >- m_rareData->m_privateNames.set(key.get(), PrivateSymbolImpl::create(*key.get())); >+ for (auto entry : symbolTable->privateNames()) >+ m_rareData->m_privateNames.set(entry.key.get(), PrivateSymbolImpl::create(*entry.key.get())); > } > } > >diff --git a/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h b/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h >index f9b7e2adbfe..0d95747a53f 100644 >--- a/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h >+++ b/Source/JavaScriptCore/runtime/ModuleProgramExecutable.h >@@ -63,7 +63,7 @@ public: > > DECLARE_INFO; > >- ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Module, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); } >+ ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, PrivateBrandRequirement::None, false, ConstructorKind::None, JSParserScriptMode::Module, SuperBinding::NotNeeded, SourceParseMode::ModuleEvaluateMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); } > > UnlinkedModuleProgramCodeBlock* unlinkedModuleProgramCodeBlock() { return m_unlinkedModuleProgramCodeBlock.get(); } > >diff --git a/Source/JavaScriptCore/runtime/Options.h b/Source/JavaScriptCore/runtime/Options.h >index 29c6b323b81..e1886d6a3bb 100644 >--- a/Source/JavaScriptCore/runtime/Options.h >+++ b/Source/JavaScriptCore/runtime/Options.h >@@ -519,6 +519,7 @@ constexpr bool enableWebAssemblyStreamingApi = false; > v(double, validateAbstractInterpreterStateProbability, 0.5, Normal, nullptr) \ > v(optionString, dumpJITMemoryPath, nullptr, Restricted, nullptr) \ > v(bool, useClassFields, true, Normal, "If true, the parser will understand data fields inside classes.") \ >+ v(bool, usePrivateMethods, true, Normal, "If true, the parser will understand private methods and accessors. This requires useClassFeilds to be true.") \ > > enum OptionEquivalence { > SameOption, >diff --git a/Source/JavaScriptCore/runtime/ProgramExecutable.h b/Source/JavaScriptCore/runtime/ProgramExecutable.h >index b96844456a3..dd2641a6f96 100644 >--- a/Source/JavaScriptCore/runtime/ProgramExecutable.h >+++ b/Source/JavaScriptCore/runtime/ProgramExecutable.h >@@ -71,7 +71,7 @@ public: > > DECLARE_INFO; > >- ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); } >+ ExecutableInfo executableInfo() const { return ExecutableInfo(usesEval(), isStrictMode(), false, PrivateBrandRequirement::None, false, ConstructorKind::None, JSParserScriptMode::Classic, SuperBinding::NotNeeded, SourceParseMode::ProgramMode, derivedContextType(), isArrowFunctionContext(), false, EvalContextType::None); } > > TemplateObjectMap& ensureTemplateObjectMap(VM&); > >diff --git a/Source/JavaScriptCore/runtime/Symbol.cpp b/Source/JavaScriptCore/runtime/Symbol.cpp >index c8be03af825..838ba9f5a22 100644 >--- a/Source/JavaScriptCore/runtime/Symbol.cpp >+++ b/Source/JavaScriptCore/runtime/Symbol.cpp >@@ -133,4 +133,11 @@ Symbol* Symbol::create(VM& vm, SymbolImpl& uid) > return symbol; > } > >+Symbol* Symbol::createPrivate(VM& vm, PrivateSymbolImpl& uid) >+{ >+ Symbol* symbol = new (NotNull, allocateCell<Symbol>(vm.heap)) Symbol(vm, uid); >+ symbol->finishCreation(vm); >+ return symbol; >+} >+ > } // namespace JSC >diff --git a/Source/JavaScriptCore/runtime/Symbol.h b/Source/JavaScriptCore/runtime/Symbol.h >index ca9942e55ae..41d71e372d9 100644 >--- a/Source/JavaScriptCore/runtime/Symbol.h >+++ b/Source/JavaScriptCore/runtime/Symbol.h >@@ -48,6 +48,7 @@ public: > static Symbol* create(VM&); > static Symbol* createWithDescription(VM&, const String&); > JS_EXPORT_PRIVATE static Symbol* create(VM&, SymbolImpl& uid); >+ static Symbol* createPrivate(VM&, PrivateSymbolImpl& uid); > > PrivateName privateName() const { return m_privateName; } > String descriptiveString() const; >diff --git a/Source/JavaScriptCore/runtime/SymbolTable.cpp b/Source/JavaScriptCore/runtime/SymbolTable.cpp >index 860c91be994..32d7133ee18 100644 >--- a/Source/JavaScriptCore/runtime/SymbolTable.cpp >+++ b/Source/JavaScriptCore/runtime/SymbolTable.cpp >@@ -188,7 +188,7 @@ SymbolTable* SymbolTable::cloneScopePart(VM& vm) > auto iter = m_rareData->m_privateNames.begin(); > auto end = m_rareData->m_privateNames.end(); > for (; iter != end; ++iter) >- result->m_rareData->m_privateNames.add(*iter); >+ result->m_rareData->m_privateNames.add(iter->key, iter->value); > } > } > >diff --git a/Source/JavaScriptCore/runtime/SymbolTable.h b/Source/JavaScriptCore/runtime/SymbolTable.h >index c6b841fde7a..19f5381eea7 100644 >--- a/Source/JavaScriptCore/runtime/SymbolTable.h >+++ b/Source/JavaScriptCore/runtime/SymbolTable.h >@@ -34,6 +34,7 @@ > #include "JSObject.h" > #include "ScopedArgumentsTable.h" > #include "TypeLocation.h" >+#include "VariableEnvironment.h" > #include "VarOffset.h" > #include "Watchpoint.h" > #include <memory> >@@ -449,8 +450,7 @@ public: > typedef HashMap<RefPtr<UniquedStringImpl>, RefPtr<TypeSet>, IdentifierRepHash> UniqueTypeSetMap; > typedef HashMap<VarOffset, RefPtr<UniquedStringImpl>> OffsetToVariableMap; > typedef Vector<SymbolTableEntry*> LocalToEntryVec; >- typedef HashSet<RefPtr<UniquedStringImpl>, StringRepHash> PrivateNameSet; >- typedef WTF::IteratorRange<typename PrivateNameSet::iterator> PrivateNameIteratorRange; >+ typedef WTF::IteratorRange<typename VariableEnvironment::PrivateNames::iterator> PrivateNameIteratorRange; > > static SymbolTable* create(VM& vm) > { >@@ -593,7 +593,7 @@ public: > bool hasPrivateNames() const { return m_rareData && m_rareData->m_privateNames.size(); } > ALWAYS_INLINE PrivateNameIteratorRange privateNames() > { >- PrivateNameSet::iterator begin, end; >+ VariableEnvironment::PrivateNames::iterator begin, end; > if (m_rareData) { > begin = m_rareData->m_privateNames.begin(); > end = m_rareData->m_privateNames.end(); >@@ -601,14 +601,14 @@ public: > return PrivateNameIteratorRange(begin, end); > } > >- void addPrivateName(UniquedStringImpl* key) >+ void addPrivateName(const RefPtr<UniquedStringImpl>& key, PrivateNameEntry value) > { > ASSERT(key && !key->isSymbol()); > if (!m_rareData) > m_rareData = std::make_unique<SymbolTableRareData>(); > >- ASSERT(!m_rareData->m_privateNames.contains(key)); >- m_rareData->m_privateNames.add(key); >+ ASSERT(m_rareData->m_privateNames.find(key) == m_rareData->m_privateNames.end()); >+ m_rareData->m_privateNames.add(key, value); > } > > template<typename Entry> >@@ -731,7 +731,7 @@ public: > OffsetToVariableMap m_offsetToVariableMap; > UniqueTypeSetMap m_uniqueTypeSetMap; > WriteBarrier<CodeBlock> m_codeBlock; >- PrivateNameSet m_privateNames; >+ VariableEnvironment::PrivateNames m_privateNames; > }; > > private:
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 194434
:
370694
|
373050
|
380859
|
390683
|
393477
|
408191
|
411896
|
411978
|
412125
|
413292
|
413857
|
415781
|
417378
|
417999
|
418748
|
418881
|
418888
|
418929
|
419624
|
419630
|
419714