Skip to content

Commit

Permalink
Implement Immutable Prototype Exotic Object
Browse files Browse the repository at this point in the history
Signed-off-by: HyukWoo Park <[email protected]>
  • Loading branch information
clover2123 authored and ksh8281 committed Apr 3, 2024
1 parent 99f7a16 commit 5a52380
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 33 deletions.
3 changes: 1 addition & 2 deletions src/builtins/BuiltinObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -347,10 +347,9 @@ static Value builtinObjectSetPrototypeOf(ExecutionState& state, Value thisValue,

// 5. Let status be O.[[SetPrototypeOf]](proto).
Object* obj = object.toObject(state);
bool status = obj->setPrototype(state, proto);

// 7. If status is false, throw a TypeError exception.
if (!status) {
if (!obj->setPrototype(state, proto)) {
ErrorObject::throwBuiltinError(state, ErrorCode::TypeError, state.context()->staticStrings().Object.string(), false, state.context()->staticStrings().setPrototypeOf.string(), "can't set prototype of this object");
return Value();
}
Expand Down
48 changes: 24 additions & 24 deletions src/builtins/BuiltinSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ static Value builtinSetConstructor(ExecutionState& state, Value thisValue, size_
// Let set be ? OrdinaryCreateFromConstructor(NewTarget, "%SetPrototype%", « [[SetData]] »).
// Set set's [[SetData]] internal slot to a new empty List.
Object* proto = Object::getPrototypeFromConstructor(state, newTarget.value(), [](ExecutionState& state, Context* constructorRealm) -> Object* {
return constructorRealm->globalObject()->setPrototype();
return constructorRealm->globalObject()->setPrototypeObject();
});
SetObject* set = new SetObject(state, proto);

Expand Down Expand Up @@ -207,43 +207,43 @@ void GlobalObject::installSet(ExecutionState& state)
m_set->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().species), desc);
}

m_setPrototype = new PrototypeObject(state);
m_setPrototype->setGlobalIntrinsicObject(state, true);
m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject = new PrototypeObject(state);
m_setPrototypeObject->setGlobalIntrinsicObject(state, true);
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().constructor), ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));

m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().clear),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().clear, builtinSetClear, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().clear),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().clear, builtinSetClear, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));

m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinSetDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().stringDelete),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().stringDelete, builtinSetDelete, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));

m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().has),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinSetHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().has),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().has, builtinSetHas, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));

m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().add),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().add, builtinSetAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().add),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().add, builtinSetAdd, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));

m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().forEach),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().forEach, builtinSetForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().forEach),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().forEach, builtinSetForEach, 1, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));

auto valuesFn = new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().values, builtinSetValues, 0, NativeFunctionInfo::Strict));
auto values = ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent));
m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().values), values);
m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().keys), values);
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().values), values);
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().keys), values);

m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().entries),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().entries, builtinSetEntries, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().entries),
ObjectPropertyDescriptor(new NativeFunctionObject(state, NativeFunctionInfo(state.context()->staticStrings().entries, builtinSetEntries, 0, NativeFunctionInfo::Strict)), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));

m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().iterator),
ObjectPropertyDescriptor(valuesFn, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));

m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(state.context()->staticStrings().Set.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(state.context()->staticStrings().Set.string()), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));
JSGetterSetter gs(
new NativeFunctionObject(state, NativeFunctionInfo(AtomicString(state, String::fromASCII("get size")), builtinSetSizeGetter, 0, NativeFunctionInfo::Strict)),
Value(Value::EmptyValue));
ObjectPropertyDescriptor desc(gs, ObjectPropertyDescriptor::ConfigurablePresent);
m_setPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().size), desc);
m_setPrototypeObject->directDefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().size), desc);

m_setIteratorPrototype = new PrototypeObject(state, m_iteratorPrototype);
m_setIteratorPrototype->setGlobalIntrinsicObject(state, true);
Expand All @@ -254,7 +254,7 @@ void GlobalObject::installSet(ExecutionState& state)
m_setIteratorPrototype->directDefineOwnProperty(state, ObjectPropertyName(state.context()->vmInstance()->globalSymbols().toStringTag),
ObjectPropertyDescriptor(Value(String::fromASCII("Set Iterator")), (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::ConfigurablePresent)));

m_set->setFunctionPrototype(state, m_setPrototype);
m_set->setFunctionPrototype(state, m_setPrototypeObject);
redefineOwnProperty(state, ObjectPropertyName(state.context()->staticStrings().Set),
ObjectPropertyDescriptor(m_set, (ObjectPropertyDescriptor::PresentAttribute)(ObjectPropertyDescriptor::WritablePresent | ObjectPropertyDescriptor::ConfigurablePresent)));
}
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/GlobalObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
namespace Escargot {

GlobalObject::GlobalObject(ExecutionState& state)
: PrototypeObject(state, Object::createBuiltinObjectPrototype(state))
: ImmutablePrototypeObject(state, Object::createBuiltinObjectPrototype(state))
, m_context(state.context())
#define INIT_BUILTIN_VALUE(builtin, TYPE, objName) \
, m_##builtin(nullptr)
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/GlobalObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ class FunctionObject;
F(regexpSplitMethod, FunctionObject, objName)
#define GLOBALOBJECT_BUILTIN_SET(F, objName) \
F(set, FunctionObject, objName) \
F(setPrototype, Object, objName) \
F(setPrototypeObject, Object, objName) \
F(setIteratorPrototype, Object, objName)
#define GLOBALOBJECT_BUILTIN_STRING(F, objName) \
F(string, FunctionObject, objName) \
Expand Down Expand Up @@ -318,7 +318,7 @@ class FunctionObject;

Value builtinSpeciesGetter(ExecutionState& state, Value thisValue, size_t argc, Value* argv, Optional<Object*> newTarget);

class GlobalObject : public PrototypeObject {
class GlobalObject : public ImmutablePrototypeObject {
public:
friend class GlobalEnvironmentRecord;

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/GlobalObjectProxyObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ Object* GlobalObjectProxyObject::getPrototypeObject(ExecutionState& state)
bool GlobalObjectProxyObject::setPrototype(ExecutionState& state, const Value& proto)
{
checkSecurity(state, GlobalObjectProxyObjectRef::AccessOperationType::Write, Optional<AtomicString>());
return m_target->Object::setPrototype(state, proto);
return m_target->setPrototype(state, proto);
}

Object::OwnPropertyKeyVector GlobalObjectProxyObject::ownPropertyKeys(ExecutionState& state)
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -582,7 +582,7 @@ bool Object::isConcatSpreadable(ExecutionState& state)

Object* Object::createBuiltinObjectPrototype(ExecutionState& state)
{
Object* obj = new PrototypeObject(state, PrototypeObject::__ForGlobalBuiltin__);
Object* obj = new ImmutablePrototypeObject(state, ImmutablePrototypeObject::__ForGlobalBuiltin__);
obj->markThisObjectDontNeedStructureTransitionTable();
return obj;
}
Expand Down
13 changes: 13 additions & 0 deletions src/runtime/PrototypeObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,17 @@ void PrototypeObject::markAsPrototypeObject(ExecutionState& state)
}
}

bool ImmutablePrototypeObject::setPrototype(ExecutionState& state, const Value& proto)
{
// Let current be ? O.[[GetPrototypeOf]]().
Value current = getPrototype(state);
// If SameValue(V, current) is true, return true.
if (current == proto) {
return true;
}

// Return false.
return false;
}

} // namespace Escargot
20 changes: 20 additions & 0 deletions src/runtime/PrototypeObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ class PrototypeObject : public DerivedObject {
}
};

// Immutable Prototype Exotic Objects
// An immutable prototype exotic object is an exotic object that has a [[Prototype]] internal slot
// that will not change once it is initialized.
class ImmutablePrototypeObject : public PrototypeObject {
public:
explicit ImmutablePrototypeObject(ExecutionState& state, Object* proto, size_t defaultSpace = ESCARGOT_OBJECT_BUILTIN_PROPERTY_NUMBER)
: PrototypeObject(state, proto, defaultSpace)
{
}

enum ForGlobalBuiltin { __ForGlobalBuiltin__ };
explicit ImmutablePrototypeObject(ExecutionState& state, ForGlobalBuiltin)
: PrototypeObject(state, PrototypeObject::__ForGlobalBuiltin__)
{
}

// internal [[prototype]]
virtual bool setPrototype(ExecutionState& state, const Value& proto);
};

} // namespace Escargot

#endif
2 changes: 1 addition & 1 deletion src/runtime/SetObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
namespace Escargot {

SetObject::SetObject(ExecutionState& state)
: SetObject(state, state.context()->globalObject()->setPrototype())
: SetObject(state, state.context()->globalObject()->setPrototypeObject())
{
}

Expand Down
2 changes: 1 addition & 1 deletion test/vendortest
14 changes: 14 additions & 0 deletions tools/test/v8/v8.mjsunit.status
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,20 @@
# outdated
'invalid-lhs': [SKIP],

# can't set prototype of this object
'getter-in-prototype': [SKIP],
'global-deleted-property-ic': [SKIP],
'es6/unscopables': [SKIP],
'regress/readonly3': [SKIP],
'regress/readonly5': [SKIP],
'regress/regress-186': [SKIP],
'regress/regress-447561': [SKIP],
'regress/regress-489151': [SKIP],
'regress/regress-675': [SKIP],
'regress/regress-88591': [SKIP],
'regress/regress-crbug-454091': [SKIP],
'regress/regress-crbug-513472': [SKIP],

## 15. Out of memory

# 32bit addressing on 64bit causes memory allocation failure
Expand Down

0 comments on commit 5a52380

Please sign in to comment.