[Bug]: CreateDataProperty快速路径导致static未走define语义

对于static的情况,走define语义。

Issue: #I8XNRO

Signed-off-by: lichenshuai <lichenshuai@huawei.com>
Change-Id: I271926b42288035e14c63763f207d52a3358dad6
This commit is contained in:
lichenshuai 2024-02-27 15:30:29 +08:00
parent 8ebd2047bb
commit 6b71e0b044
17 changed files with 90 additions and 38 deletions

View File

@ -576,7 +576,7 @@ GateRef AccessObjectStubBuilder::StOwnByValueWithNameSet(GateRef glue, GateRef r
Branch(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
Bind(&notClassPrototype);
{
result = SetPropertyByValue(glue, receiver, key, value, false);
result = SetPropertyByValue(glue, receiver, key, value, true, ProfileOperation(), true);
Branch(TaggedIsHole(*result), &slowPath, &notHole);
Bind(&notHole);
{
@ -621,7 +621,7 @@ GateRef AccessObjectStubBuilder::StOwnByNameWithNameSet(GateRef glue, GateRef re
Branch(IsClassPrototype(receiver), &notJSObject, &notClassPrototype);
Bind(&notClassPrototype);
{
result = SetPropertyByName(glue, receiver, key, value, true, True());
result = SetPropertyByName(glue, receiver, key, value, true, True(), ProfileOperation(), false, true);
Branch(TaggedIsHole(*result), &notJSObject, &notHole);
Bind(&notHole);
{

View File

@ -285,6 +285,7 @@ void SnapshotConstantPoolData::Record(const BytecodeInstruction &bcIns, int32_t
case BytecodeInstruction::Opcode::LDOBJBYNAME_IMM16_ID16:
case BytecodeInstruction::Opcode::STOBJBYNAME_IMM8_ID16_V8:
case BytecodeInstruction::Opcode::STOBJBYNAME_IMM16_ID16_V8:
case BytecodeInstruction::Opcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM8_ID16:
case BytecodeInstruction::Opcode::LDSUPERBYNAME_IMM16_ID16:
case BytecodeInstruction::Opcode::STSUPERBYNAME_IMM8_ID16_V8:

View File

@ -477,6 +477,7 @@ BytecodeMetaData BytecodeMetaData::InitBytecodeMetaData(const uint8_t *pc)
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
kind = BytecodeKind::ACCESSOR_BC;
break;
default:

View File

@ -437,6 +437,7 @@ public:
case EcmaOpcode::LDTHISBYNAME_IMM16_ID16:
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
case EcmaOpcode::CALLRUNTIME_CALLINIT_PREF_IMM8_V8:

View File

@ -1936,7 +1936,7 @@ DECLARE_ASM_HANDLER(HandleStownbyvaluewithnamesetImm16V8V8)
Branch(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
Bind(&notClassPrototype);
{
GateRef res = SetPropertyByValue(glue, receiver, propKey, acc, true, callback);
GateRef res = SetPropertyByValue(glue, receiver, propKey, acc, true, callback, true);
Branch(TaggedIsHole(res), &slowPath, &notHole);
Bind(&notHole);
{
@ -1979,7 +1979,7 @@ DECLARE_ASM_HANDLER(HandleStownbyvaluewithnamesetImm8V8V8)
Branch(IsClassPrototype(receiver), &slowPath, &notClassPrototype);
Bind(&notClassPrototype);
{
GateRef res = SetPropertyByValue(glue, receiver, propKey, acc, true, callback);
GateRef res = SetPropertyByValue(glue, receiver, propKey, acc, true, callback, true);
Branch(TaggedIsHole(res), &slowPath, &notHole);
Bind(&notHole);
{
@ -2098,7 +2098,7 @@ DECLARE_ASM_HANDLER(HandleStownbynamewithnamesetImm8Id16V8)
Branch(IsClassPrototype(receiver), &notJSObject, &notClassPrototype);
Bind(&notClassPrototype);
{
GateRef res = SetPropertyByName(glue, receiver, propKey, acc, true, True(), callback);
GateRef res = SetPropertyByName(glue, receiver, propKey, acc, true, True(), callback, false, true);
Branch(TaggedIsHole(res), &notJSObject, &notHole);
Bind(&notHole);
{
@ -2140,7 +2140,7 @@ DECLARE_ASM_HANDLER(HandleStownbynamewithnamesetImm16Id16V8)
Branch(IsClassPrototype(receiver), &notJSObject, &notClassPrototype);
Bind(&notClassPrototype);
{
GateRef res = SetPropertyByName(glue, receiver, propKey, acc, true, True(), callback);
GateRef res = SetPropertyByName(glue, receiver, propKey, acc, true, True(), callback, false, true);
Branch(TaggedIsHole(res), &notJSObject, &notHole);
Bind(&notHole);
{

View File

@ -3336,7 +3336,7 @@ GateRef StubBuilder::FindTransitions(GateRef glue, GateRef receiver, GateRef hcl
}
GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index, GateRef value, bool useOwn,
ProfileOperation callback)
ProfileOperation callback, bool defineSemantics)
{
auto env = GetEnvironment();
Label entry(env);
@ -3352,7 +3352,7 @@ GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef
Label isJsCOWArray(env);
Label isNotJsCOWArray(env);
Label setElementsArray(env);
if (!useOwn) {
if (!useOwn && !defineSemantics) {
Jump(&loopHead);
LoopBegin(&loopHead);
}
@ -3461,7 +3461,9 @@ GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef
Label notAccessor(env);
Branch(IsAccessor(attr), &isAccessor, &notAccessor);
Bind(&isAccessor);
{
if (defineSemantics) {
Jump(&exit);
} else {
GateRef accessor = GetValueFromDictionary<NumberDictionary>(elements, entryA);
Label shouldCall(env);
Branch(ShouldCallSetter(receiver, *holder, accessor, attr), &shouldCall, &notAccessor);
@ -3544,7 +3546,7 @@ GateRef StubBuilder::SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef
}
GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef key, GateRef value,
bool useOwn, GateRef isInternal, ProfileOperation callback, bool canUseIsInternal)
bool useOwn, GateRef isInternal, ProfileOperation callback, bool canUseIsInternal, bool defineSemantics)
{
auto env = GetEnvironment();
Label entryPass(env);
@ -3636,7 +3638,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
GateRef entry = FindElementWithCache(glue, layOutInfo, hclass, key, propsNum);
Label hasEntry(env);
// if branch condition : entry != -1
if (useOwn) {
if (useOwn || defineSemantics) {
Branch(Int32NotEqual(entry, Int32(-1)), &hasEntry, &ifEnd);
} else {
Branch(Int32NotEqual(entry, Int32(-1)), &hasEntry, &loopExit);
@ -3650,7 +3652,9 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
Label notAccessor(env);
Branch(IsAccessor(attr), &isAccessor, &notAccessor);
Bind(&isAccessor);
{
if (defineSemantics) {
Jump(&exit);
} else {
// auto accessor = JSObject::Cast(holder)->GetProperty(hclass, attr)
GateRef accessor = JSObjectGetProperty(*holder, hclass, attr);
Label shouldCall(env);
@ -3668,7 +3672,9 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
Label notWritable(env);
Branch(IsWritable(attr), &writable, &notWritable);
Bind(&notWritable);
{
if (defineSemantics) {
Jump(&exit);
} else {
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
result = Exception();
@ -3698,7 +3704,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
Jump(&noNeedStore);
}
Bind(&noNeedStore);
if (useOwn) {
if (useOwn || defineSemantics) {
Jump(&ifEnd);
} else {
Jump(&loopExit);
@ -3707,7 +3713,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
}
Bind(&notTS);
Label holdEqualsRecv(env);
if (useOwn) {
if (useOwn || defineSemantics) {
Branch(Equal(*holder, receiver), &holdEqualsRecv, &ifEnd);
} else {
Branch(Equal(*holder, receiver), &holdEqualsRecv, &afterLoop);
@ -3736,7 +3742,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
GateRef entry1 = FindEntryFromNameDictionary(glue, array, key);
Label notNegtiveOne(env);
// if branch condition : entry != -1
if (useOwn) {
if (useOwn || defineSemantics) {
Branch(Int32NotEqual(entry1, Int32(-1)), &notNegtiveOne, &ifEnd);
} else {
Branch(Int32NotEqual(entry1, Int32(-1)), &notNegtiveOne, &loopExit);
@ -3750,7 +3756,9 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
// if branch condition : UNLIKELY(attr.IsAccessor())
Branch(IsAccessor(attr1), &isAccessor1, &notAccessor1);
Bind(&isAccessor1);
{
if (defineSemantics) {
Jump(&exit);
} else {
// auto accessor = dict->GetValue(entry)
GateRef accessor1 = GetValueFromDictionary<NameDictionary>(array, entry1);
Label shouldCall1(env);
@ -3767,7 +3775,9 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
Label notWritable1(env);
Branch(IsWritable(attr1), &writable1, &notWritable1);
Bind(&notWritable1);
{
if (defineSemantics) {
Jump(&exit);
} else {
GateRef taggedId = Int32(GET_MESSAGE_STRING_ID(SetReadOnlyProperty));
CallRuntime(glue, RTSTUB_ID(ThrowTypeError), { IntToTaggedInt(taggedId) });
result = Exception();
@ -3797,7 +3807,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
}
}
}
if (useOwn) {
if (useOwn || defineSemantics) {
Bind(&ifEnd);
} else {
Bind(&loopExit);
@ -3851,7 +3861,7 @@ GateRef StubBuilder::SetPropertyByName(GateRef glue, GateRef receiver, GateRef k
}
GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, bool useOwn,
ProfileOperation callback)
ProfileOperation callback, bool defineSemantics)
{
auto env = GetEnvironment();
Label subEntry1(env);
@ -3891,7 +3901,7 @@ GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef
Branch(Int32GreaterThanOrEqual(index, Int32(0)), &validIndex, &notValidIndex);
Bind(&validIndex);
{
result = SetPropertyByIndex(glue, receiver, index, value, useOwn);
result = SetPropertyByIndex(glue, receiver, index, value, useOwn, callback, defineSemantics);
Jump(&exit);
}
Bind(&notValidIndex);
@ -3938,7 +3948,8 @@ GateRef StubBuilder::SetPropertyByValue(GateRef glue, GateRef receiver, GateRef
CheckDetectorName(glue, *varKey, &setByName, &exit);
Bind(&setByName);
{
result = SetPropertyByName(glue, receiver, *varKey, value, useOwn, *isInternal, callback, true);
result = SetPropertyByName(glue, receiver, *varKey, value, useOwn, *isInternal, callback,
true, defineSemantics);
Jump(&exit);
}
}

View File

@ -632,12 +632,12 @@ public:
ProfileOperation callback = ProfileOperation());
void FastSetPropertyByIndex(GateRef glue, GateRef obj, GateRef index, GateRef value);
GateRef SetPropertyByIndex(GateRef glue, GateRef receiver, GateRef index,
GateRef value, bool useOwn, ProfileOperation callback = ProfileOperation());
GateRef value, bool useOwn, ProfileOperation callback = ProfileOperation(), bool defineSemantics = false);
GateRef SetPropertyByName(GateRef glue, GateRef receiver, GateRef key,
GateRef value, bool useOwn, GateRef isInternal, ProfileOperation callback = ProfileOperation(),
bool canUseIsInternal = false); // Crawl prototype chain
bool canUseIsInternal = false, bool defineSemantics = false); // Crawl prototype chain
GateRef SetPropertyByValue(GateRef glue, GateRef receiver, GateRef key, GateRef value, bool useOwn,
ProfileOperation callback = ProfileOperation());
ProfileOperation callback = ProfileOperation(), bool defineSemantics = false);
GateRef GetParentEnv(GateRef object);
GateRef GetPropertiesFromLexicalEnv(GateRef object, GateRef index);
void SetPropertiesToLexicalEnv(GateRef glue, GateRef object, GateRef index, GateRef value);

View File

@ -82,6 +82,7 @@ void TSInlineLowering::CandidateInlineCall(GateRef gate, ChunkQueue<InlineTypeIn
break;
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
CandidateAccessor(gate, workList, CallKind::CALL_SETTER);

View File

@ -45,7 +45,8 @@ void InitializationAnalysis::Analyse(GateRef gate)
EcmaOpcode ecmaOpcode = acc_.GetByteCodeOpcode(gate);
switch (ecmaOpcode) {
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8: {
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8: {
CollectInitializationType(gate, ThisUsage::INDEFINITE_THIS);
CollectInitializationInfo(gate, ThisUsage::INDEFINITE_THIS);
break;
@ -203,6 +204,7 @@ bool InitializationAnalysis::CheckSimpleJSGate(GateRef gate, const uint16_t inde
}
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
case EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM8:
@ -288,6 +290,7 @@ bool InitializationAnalysis::HasEscapedThis(GateRef gate) const
switch (ecmaOpcode) {
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:
case EcmaOpcode::STTHISBYNAME_IMM16_ID16:
case EcmaOpcode::THROW_IFSUPERNOTCORRECTCALL_PREF_IMM8:

View File

@ -365,6 +365,7 @@ bool MethodTypeInfer::Infer(GateRef gate)
return InferLdExternalModuleVar(gate);
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
return InferStObjByName(gate);
default:
break;

View File

@ -47,6 +47,7 @@ void PGOTypeInfer::RunTypeInfer(GateRef gate)
break;
case EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8:
case EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8:
case EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8:
InferStObjByName(gate, false);
break;
case EcmaOpcode::STTHISBYNAME_IMM8_ID16:

View File

@ -568,14 +568,14 @@ void TypedBytecodeLowering::LowerTypedStObjByName(GateRef gate)
// The framestate of Call and Accessor related instructions directives is placed on IR. Using the depend edge to
// climb up and find the nearest framestate for other instructions
if (opcode == EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8 ||
opcode == EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8 ||
if (opcode == EcmaOpcode::STOWNBYNAME_IMM8_ID16_V8 ||
opcode == EcmaOpcode::STOWNBYNAME_IMM16_ID16_V8) {
frameState = acc_.FindNearestFrameState(builder_.GetDepend());
} else if (opcode == EcmaOpcode::STOBJBYNAME_IMM8_ID16_V8 ||
opcode == EcmaOpcode::STOBJBYNAME_IMM16_ID16_V8 ||
opcode == EcmaOpcode::STTHISBYNAME_IMM8_ID16 ||
opcode == EcmaOpcode::STTHISBYNAME_IMM16_ID16) {
opcode == EcmaOpcode::STTHISBYNAME_IMM16_ID16 ||
opcode == EcmaOpcode::DEFINEFIELDBYNAME_IMM8_ID16_V8) {
frameState = acc_.GetFrameState(gate);
} else {
UNREACHABLE();

View File

@ -2797,7 +2797,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
JSTaggedValue propKey = GET_VREG_VALUE(v1);
JSTaggedValue value = GET_ACC();
// fast path
JSTaggedValue res = FastRuntimeStub::SetPropertyByValue<ObjectFastOperator::Status::UseOwn>
JSTaggedValue res = FastRuntimeStub::SetPropertyByValue<ObjectFastOperator::Status::DefineSemantics>
(thread, receiver, propKey, value);
// SetPropertyByValue maybe gc need update the value
@ -2838,7 +2838,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
JSTaggedValue value = GET_ACC();
// fast path
SAVE_ACC();
JSTaggedValue res = FastRuntimeStub::SetPropertyByName<ObjectFastOperator::Status::UseOwn>
JSTaggedValue res = FastRuntimeStub::SetPropertyByName<ObjectFastOperator::Status::DefineSemantics>
(thread, receiver, propKey, value);
if (!res.IsHole()) {
INTERPRETER_RETURN_IF_ABRUPT(res);
@ -6655,7 +6655,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
JSTaggedValue propKey = GET_VREG_VALUE(v1);
JSTaggedValue value = GET_ACC();
// fast path
JSTaggedValue res = FastRuntimeStub::SetPropertyByValue<ObjectFastOperator::Status::UseOwn>
JSTaggedValue res = FastRuntimeStub::SetPropertyByValue<ObjectFastOperator::Status::DefineSemantics>
(thread, receiver, propKey, value);
// SetPropertyByValue maybe gc need update the value
@ -6697,7 +6697,7 @@ NO_UB_SANITIZE void EcmaInterpreter::RunInternal(JSThread *thread, const uint8_t
JSTaggedValue value = GET_ACC();
// fast path
SAVE_ACC();
JSTaggedValue res = FastRuntimeStub::SetPropertyByName<ObjectFastOperator::Status::UseOwn>
JSTaggedValue res = FastRuntimeStub::SetPropertyByName<ObjectFastOperator::Status::DefineSemantics>
(thread, receiver, propKey, value);
if (!res.IsHole()) {
INTERPRETER_RETURN_IF_ABRUPT(res);

View File

@ -1614,7 +1614,10 @@ bool JSObject::CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &ob
{
ASSERT_PRINT(obj->IsECMAObject(), "Obj is not a valid object");
ASSERT_PRINT(JSTaggedValue::IsPropertyKey(key), "Key is not a property key");
auto result = ObjectFastOperator::SetPropertyByValue<ObjectFastOperator::Status::UseOwn>(
if (!JSHandle<JSTaggedValue>::Cast(obj)->IsJSShared()) {
sCheckMode = SCheckMode::CHECK;
}
auto result = ObjectFastOperator::SetPropertyByValue<ObjectFastOperator::Status::DefineSemantics>(
thread, obj.GetTaggedValue(), key.GetTaggedValue(), value.GetTaggedValue(), sCheckMode);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, false);
if (!result.IsHole()) {
@ -1628,7 +1631,7 @@ bool JSObject::CreateDataProperty(JSThread *thread, const JSHandle<JSObject> &ob
const JSHandle<JSTaggedValue> &value)
{
ASSERT_PRINT(obj->IsECMAObject(), "Obj is not a valid object");
auto result = ObjectFastOperator::SetPropertyByIndex<ObjectFastOperator::Status::UseOwn>
auto result = ObjectFastOperator::SetPropertyByIndex<ObjectFastOperator::Status::DefineSemantics>
(thread, obj.GetTaggedValue(), index, value.GetTaggedValue());
if (!result.IsHole()) {
return !result.IsException();

View File

@ -214,12 +214,18 @@ JSTaggedValue ObjectFastOperator::SetPropertyByName(JSThread *thread, JSTaggedVa
PropertyAttributes attr(layoutInfo->GetAttr(entry));
ASSERT(static_cast<int>(attr.GetOffset()) == entry);
if (UNLIKELY(attr.IsAccessor())) {
if (DefineSemantics(status) && sCheckMode == SCheckMode::CHECK) {
return JSTaggedValue::Hole();
}
auto accessor = JSObject::Cast(holder)->GetProperty(hclass, attr);
if (ShouldCallSetter(receiver, holder, accessor, attr)) {
return CallSetter(thread, receiver, value, accessor);
}
}
if (UNLIKELY(!attr.IsWritable())) {
if (DefineSemantics(status) && sCheckMode == SCheckMode::CHECK) {
return JSTaggedValue::Hole();
}
[[maybe_unused]] EcmaHandleScope handleScope(thread);
THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(SetReadOnlyProperty),
JSTaggedValue::Exception());
@ -257,12 +263,18 @@ JSTaggedValue ObjectFastOperator::SetPropertyByName(JSThread *thread, JSTaggedVa
if (entry != -1) {
auto attr = dict->GetAttributes(entry);
if (UNLIKELY(attr.IsAccessor())) {
if (DefineSemantics(status) && sCheckMode == SCheckMode::CHECK) {
return JSTaggedValue::Hole();
}
auto accessor = dict->GetValue(entry);
if (ShouldCallSetter(receiver, holder, accessor, attr)) {
return CallSetter(thread, receiver, value, accessor);
}
}
if (UNLIKELY(!attr.IsWritable())) {
if (DefineSemantics(status) && sCheckMode == SCheckMode::CHECK) {
return JSTaggedValue::Hole();
}
[[maybe_unused]] EcmaHandleScope handleScope(thread);
THROW_TYPE_ERROR_AND_RETURN(thread, GET_MESSAGE_STRING(SetReadOnlyProperty),
JSTaggedValue::Exception());
@ -280,7 +292,7 @@ JSTaggedValue ObjectFastOperator::SetPropertyByName(JSThread *thread, JSTaggedVa
return JSTaggedValue::Undefined();
}
}
if (UseOwn(status)) {
if (UseOwn(status) || DefineSemantics(status)) {
break;
}
holder = hclass->GetPrototype();
@ -420,6 +432,9 @@ JSTaggedValue ObjectFastOperator::SetPropertyByIndex(JSThread *thread, JSTaggedV
break;
}
if (UNLIKELY(attr.IsAccessor())) {
if (DefineSemantics(status)) {
return JSTaggedValue::Hole();
}
auto accessor = dict->GetValue(entry);
if (ShouldCallSetter(receiver, holder, accessor, attr)) {
return CallSetter(thread, receiver, value, accessor);
@ -430,7 +445,7 @@ JSTaggedValue ObjectFastOperator::SetPropertyByIndex(JSThread *thread, JSTaggedV
}
return JSTaggedValue::Hole();
}
if (UseOwn(status)) {
if (UseOwn(status) || DefineSemantics(status)) {
break;
}
holder = JSObject::Cast(holder)->GetJSHClass()->GetPrototype();

View File

@ -29,6 +29,7 @@ public:
None = 0x00UL,
UseOwn = 0x01UL,
GetInternal = 0x1UL << 1,
DefineSemantics = 0x1UL << 2,
};
static inline bool UseOwn(Status status)
@ -41,6 +42,11 @@ public:
return (static_cast<int32_t>(status) & static_cast<int32_t>(Status::GetInternal)) > 0;
}
static inline bool DefineSemantics(Status status)
{
return (static_cast<int32_t>(status) & static_cast<int32_t>(Status::DefineSemantics)) > 0;
}
static inline std::pair<JSTaggedValue, bool> HasOwnProperty(JSThread *thread,
JSTaggedValue receiver, JSTaggedValue key);
template<Status status = Status::None>

View File

@ -117,4 +117,12 @@ class Class2024 {
#c = foo;
}
var class2024 = new Class2024();
print("test successful!");
print("test successful!");
class StaticTest {
static set a(a) {
print(a);
}
static a = 1; // expect no print
static length = 1; // expect no TypeError
}