Skip to content

Commit

Permalink
[JSC] Different @@species getter for each constructor
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=267039

Reviewed by Keith Miller.

In JavaScriptCore, `Object.getOwnPropertyDescriptor(Array, Symbol.species).get === Object.getOwnPropertyDescriptor(RegExp, Symbol.species).get` evaluates to true.
This patch changes the @@species getters of each constructor to be different objects, so that the result of this expression becomes false.
Remove the global `m_speciesGetterSetter` and create `m_arraySpeciesGetterSetter` and `m_regExpSpeciesGetterSetter` and ... for each constructor.
Instead of passing the `GetterSetter*` type values as arguments to the create function of each constructor, refer to them from the `globalObject`.

https://tc39.es/ecma262/#sec-get-regexp-@@species
https://tc39.es/ecma262/#sec-get-array-@@species
https://tc39.es/ecma262/#sec-get-%typedarray%-@@species
https://tc39.es/ecma262/#sec-get-map-@@species
https://tc39.es/ecma262/#sec-get-set-@@species
https://tc39.es/ecma262/#sec-get-arraybuffer-@@species
https://tc39.es/ecma262/#sec-sharedarraybuffer-@@species
https://tc39.es/ecma262/#sec-get-promise-@@species

* JSTests/stress/species-equivalence-typedarray.js: Added.
(shouldBe):
(readTypedArraySymbolSpeciesGetter):
(runTest):
* JSTests/stress/species-equivalence.js: Added.
(shouldNotBe):
(readSymbolSpeciesGetter):
(runTest):
* Source/JavaScriptCore/runtime/ArrayConstructor.cpp:
(JSC::ArrayConstructor::finishCreation):
* Source/JavaScriptCore/runtime/ArrayConstructor.h:
* Source/JavaScriptCore/runtime/BigIntConstructor.h:
* Source/JavaScriptCore/runtime/BooleanConstructor.cpp:
(JSC::BooleanConstructor::create):
* Source/JavaScriptCore/runtime/BooleanConstructor.h:
* Source/JavaScriptCore/runtime/DateConstructor.h:
* Source/JavaScriptCore/runtime/ErrorConstructor.h:
* Source/JavaScriptCore/runtime/FinalizationRegistryConstructor.h:
* Source/JavaScriptCore/runtime/JSArrayBufferConstructor.cpp:
(JSC::JSGenericArrayBufferConstructor<sharingMode>::finishCreation):
* Source/JavaScriptCore/runtime/JSArrayBufferConstructor.h:
* Source/JavaScriptCore/runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildrenImpl):
(JSC::JSGlobalObject::tryInstallSpeciesWatchpoint):
(JSC::JSGlobalObject::installArraySpeciesWatchpoint):
(JSC::JSGlobalObject::tryInstallArrayBufferSpeciesWatchpoint):
(JSC::JSGlobalObject::tryInstallTypedArraySpeciesWatchpoint):
(JSC::JSGlobalObject::installTypedArrayConstructorSpeciesWatchpoint):
* Source/JavaScriptCore/runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::arraySpeciesGetterSetter const):
(JSC::JSGlobalObject::typedArraySpeciesGetterSetter const):
(JSC::JSGlobalObject::speciesGetterSetter const): Deleted.
* Source/JavaScriptCore/runtime/JSGlobalObjectInlines.h:
(JSC::JSGlobalObject::arrayBufferSpeciesGetterSetter const):
* Source/JavaScriptCore/runtime/JSInternalPromiseConstructor.cpp:
(JSC::JSInternalPromiseConstructor::create):
* Source/JavaScriptCore/runtime/JSInternalPromiseConstructor.h:
* Source/JavaScriptCore/runtime/JSPromiseConstructor.cpp:
(JSC::JSPromiseConstructor::create):
(JSC::JSPromiseConstructor::finishCreation):
* Source/JavaScriptCore/runtime/JSPromiseConstructor.h:
* Source/JavaScriptCore/runtime/JSTypedArrayViewConstructor.cpp:
(JSC::JSTypedArrayViewConstructor::finishCreation):
* Source/JavaScriptCore/runtime/JSTypedArrayViewConstructor.h:
* Source/JavaScriptCore/runtime/MapConstructor.cpp:
(JSC::MapConstructor::finishCreation):
* Source/JavaScriptCore/runtime/MapConstructor.h:
* Source/JavaScriptCore/runtime/NumberConstructor.cpp:
(JSC::NumberConstructor::create):
* Source/JavaScriptCore/runtime/NumberConstructor.h:
* Source/JavaScriptCore/runtime/RegExpConstructor.cpp:
(JSC::RegExpConstructor::finishCreation):
* Source/JavaScriptCore/runtime/RegExpConstructor.h:
* Source/JavaScriptCore/runtime/SetConstructor.cpp:
(JSC::SetConstructor::finishCreation):
* Source/JavaScriptCore/runtime/SetConstructor.h:
* Source/JavaScriptCore/runtime/ShadowRealmConstructor.h:
* Source/JavaScriptCore/runtime/StringConstructor.cpp:
(JSC::StringConstructor::create):
* Source/JavaScriptCore/runtime/StringConstructor.h:
* Source/JavaScriptCore/runtime/SymbolConstructor.h:
* Source/JavaScriptCore/runtime/WeakMapConstructor.h:
* Source/JavaScriptCore/runtime/WeakObjectRefConstructor.h:
* Source/JavaScriptCore/runtime/WeakSetConstructor.h:

Canonical link: https://commits.webkit.org/275064@main
  • Loading branch information
sosukesuzuki authored and kmiller68 committed Feb 20, 2024
1 parent 29ee719 commit d91d519
Show file tree
Hide file tree
Showing 36 changed files with 175 additions and 75 deletions.
32 changes: 32 additions & 0 deletions JSTests/stress/species-equivalence-typedarray.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
function shouldBe(actual, expected) {
if (actual !== expected)
throw new Error("Failed assertion: actual " + actual + " should be " + expected);
}

function readTypedArraySymbolSpeciesGetter(constructor) {
return Object.getOwnPropertyDescriptor(Object.getPrototypeOf(constructor), Symbol.species).get;
}

function runTest(constructors) {
for (let i = 0; i < constructors.length; i++) {
for (let j = 0; j < constructors.length; j++) {
if (i !== j) {
shouldBe(readTypedArraySymbolSpeciesGetter(constructors[i]), readTypedArraySymbolSpeciesGetter(constructors[j]));
}
}
}
}

const constructors = [
Int8Array,
Uint8Array,
Uint8ClampedArray,
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
Float64Array
];

runTest(constructors);
31 changes: 31 additions & 0 deletions JSTests/stress/species-equivalence.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
function shouldNotBe(actual, expected) {
if (actual === expected)
throw new Error("Failed assertion: actual " + actual + " should not be " + expected);
}

function readSymbolSpeciesGetter(constructor) {
return Object.getOwnPropertyDescriptor(constructor, Symbol.species).get;
}

function runTest(constructors) {
for (let i = 0; i < constructors.length; i++) {
for (let j = 0; j < constructors.length; j++) {
if (i !== j) {
shouldNotBe(readSymbolSpeciesGetter(constructors[i]), readSymbolSpeciesGetter(constructors[j]));
}
}
}
}

const constructors = [
Array,
RegExp,
Set,
Map,
Promise,
ArrayBuffer,
SharedArrayBuffer,
Object.getPrototypeOf(Uint16Array)
];

runTest(constructors);
4 changes: 2 additions & 2 deletions Source/JavaScriptCore/runtime/ArrayConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ ArrayConstructor::ArrayConstructor(VM& vm, Structure* structure)
{
}

void ArrayConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject, ArrayPrototype* arrayPrototype, GetterSetter* speciesSymbol)
void ArrayConstructor::finishCreation(VM& vm, JSGlobalObject* globalObject, ArrayPrototype* arrayPrototype)
{
Base::finishCreation(vm, 1, vm.propertyNames->Array.string(), PropertyAdditionMode::WithoutStructureTransition);
putDirectWithoutTransition(vm, vm.propertyNames->prototype, arrayPrototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->speciesSymbol, speciesSymbol, PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->speciesSymbol, globalObject->arraySpeciesGetterSetter(), PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isArray, arrayConstructorIsArrayCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));

JSC_BUILTIN_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().fromPrivateName(), arrayConstructorFromCodeGenerator, static_cast<unsigned>(PropertyAttribute::DontEnum));
Expand Down
6 changes: 3 additions & 3 deletions Source/JavaScriptCore/runtime/ArrayConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,10 @@ class ArrayConstructor final : public InternalFunction {
typedef InternalFunction Base;
static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;

static ArrayConstructor* create(VM& vm, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype, GetterSetter* speciesSymbol)
static ArrayConstructor* create(VM& vm, JSGlobalObject* globalObject, Structure* structure, ArrayPrototype* arrayPrototype)
{
ArrayConstructor* constructor = new (NotNull, allocateCell<ArrayConstructor>(vm)) ArrayConstructor(vm, structure);
constructor->finishCreation(vm, globalObject, arrayPrototype, speciesSymbol);
constructor->finishCreation(vm, globalObject, arrayPrototype);
return constructor;
}

Expand All @@ -50,7 +50,7 @@ class ArrayConstructor final : public InternalFunction {

private:
ArrayConstructor(VM&, Structure*);
void finishCreation(VM&, JSGlobalObject*, ArrayPrototype*, GetterSetter* speciesSymbol);
void finishCreation(VM&, JSGlobalObject*, ArrayPrototype*);
};
STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ArrayConstructor, InternalFunction);

Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/BigIntConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class BigIntConstructor final : public InternalFunction {
using Base = InternalFunction;
static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;

static BigIntConstructor* create(VM& vm, Structure* structure, BigIntPrototype* bigIntPrototype, GetterSetter*)
static BigIntConstructor* create(VM& vm, Structure* structure, BigIntPrototype* bigIntPrototype)
{
BigIntConstructor* constructor = new (NotNull, allocateCell<BigIntConstructor>(vm)) BigIntConstructor(vm, structure);
constructor->finishCreation(vm, bigIntPrototype);
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/BooleanConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void BooleanConstructor::finishCreation(VM& vm, BooleanPrototype* booleanPrototy
putDirectWithoutTransition(vm, vm.propertyNames->name, jsString(vm, vm.propertyNames->Boolean.string()), PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);
}

BooleanConstructor* BooleanConstructor::create(VM& vm, Structure* structure, BooleanPrototype* booleanPrototype, GetterSetter*)
BooleanConstructor* BooleanConstructor::create(VM& vm, Structure* structure, BooleanPrototype* booleanPrototype)
{
JSGlobalObject* globalObject = structure->globalObject();
NativeExecutable* executable = vm.getHostFunction(callBooleanConstructor, ImplementationVisibility::Public, BooleanConstructorIntrinsic, constructWithBooleanConstructor, nullptr, vm.propertyNames->Boolean.string());
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/BooleanConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class BooleanConstructor final : public JSFunction {
using Base = JSFunction;
static constexpr unsigned StructureFlags = Base::StructureFlags;

static BooleanConstructor* create(VM&, Structure*, BooleanPrototype*, GetterSetter*);
static BooleanConstructor* create(VM&, Structure*, BooleanPrototype*);

DECLARE_INFO;

Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/DateConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DateConstructor final : public InternalFunction {
typedef InternalFunction Base;
static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;

static DateConstructor* create(VM& vm, Structure* structure, DatePrototype* datePrototype, GetterSetter*)
static DateConstructor* create(VM& vm, Structure* structure, DatePrototype* datePrototype)
{
DateConstructor* constructor = new (NotNull, allocateCell<DateConstructor>(vm)) DateConstructor(vm, structure);
constructor->finishCreation(vm, datePrototype);
Expand Down
2 changes: 1 addition & 1 deletion Source/JavaScriptCore/runtime/ErrorConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class ErrorConstructor final : public InternalFunction {
using Base = InternalFunction;
static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesPut;

static ErrorConstructor* create(VM& vm, Structure* structure, ErrorPrototype* errorPrototype, GetterSetter*)
static ErrorConstructor* create(VM& vm, Structure* structure, ErrorPrototype* errorPrototype)
{
ErrorConstructor* constructor = new (NotNull, allocateCell<ErrorConstructor>(vm)) ErrorConstructor(vm, structure);
constructor->finishCreation(vm, errorPrototype);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class FinalizationRegistryConstructor final : public InternalFunction {
public:
using Base = InternalFunction;

static FinalizationRegistryConstructor* create(VM& vm, Structure* structure, FinalizationRegistryPrototype* prototype, GetterSetter*)
static FinalizationRegistryConstructor* create(VM& vm, Structure* structure, FinalizationRegistryPrototype* prototype)
{
FinalizationRegistryConstructor* constructor = new (NotNull, allocateCell<FinalizationRegistryConstructor>(vm)) FinalizationRegistryConstructor(vm, structure);
constructor->finishCreation(vm, prototype);
Expand Down
7 changes: 4 additions & 3 deletions Source/JavaScriptCore/runtime/JSArrayBufferConstructor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,15 @@ JSGenericArrayBufferConstructor<sharingMode>::JSGenericArrayBufferConstructor(VM
}

template<ArrayBufferSharingMode sharingMode>
void JSGenericArrayBufferConstructor<sharingMode>::finishCreation(VM& vm, JSArrayBufferPrototype* prototype, GetterSetter* speciesSymbol)
void JSGenericArrayBufferConstructor<sharingMode>::finishCreation(VM& vm, JSArrayBufferPrototype* prototype)
{
Base::finishCreation(vm, 1, arrayBufferSharingModeName(sharingMode), PropertyAdditionMode::WithoutStructureTransition);
putDirectWithoutTransition(vm, vm.propertyNames->prototype, prototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->speciesSymbol, speciesSymbol, PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);

JSGlobalObject* globalObject = this->globalObject();
putDirectNonIndexAccessorWithoutTransition(vm, vm.propertyNames->speciesSymbol, globalObject->arrayBufferSpeciesGetterSetter(sharingMode), PropertyAttribute::Accessor | PropertyAttribute::ReadOnly | PropertyAttribute::DontEnum);

if (sharingMode == ArrayBufferSharingMode::Default) {
JSGlobalObject* globalObject = this->globalObject();
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->isView, arrayBufferFuncIsView, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, ImplementationVisibility::Public);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().isViewPrivateName(), arrayBufferFuncIsView, static_cast<unsigned>(PropertyAttribute::DontEnum), 1, ImplementationVisibility::Public);
}
Expand Down
6 changes: 3 additions & 3 deletions Source/JavaScriptCore/runtime/JSArrayBufferConstructor.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,11 @@ class JSGenericArrayBufferConstructor final : public InternalFunction {
public:
using Base = InternalFunction;

static JSGenericArrayBufferConstructor* create(VM& vm, Structure* structure, JSArrayBufferPrototype* prototype, GetterSetter* speciesSymbol)
static JSGenericArrayBufferConstructor* create(VM& vm, Structure* structure, JSArrayBufferPrototype* prototype)
{
JSGenericArrayBufferConstructor* result =
new (NotNull, allocateCell<JSGenericArrayBufferConstructor>(vm)) JSGenericArrayBufferConstructor(vm, structure);
result->finishCreation(vm, prototype, speciesSymbol);
result->finishCreation(vm, prototype);
return result;
}

Expand All @@ -55,7 +55,7 @@ class JSGenericArrayBufferConstructor final : public InternalFunction {

private:
JSGenericArrayBufferConstructor(VM&, Structure*);
void finishCreation(VM&, JSArrayBufferPrototype*, GetterSetter* speciesSymbol);
void finishCreation(VM&, JSArrayBufferPrototype*);
};

using JSArrayBufferConstructor = JSGenericArrayBufferConstructor<ArrayBufferSharingMode::Default>;
Expand Down
Loading

0 comments on commit d91d519

Please sign in to comment.