From 6aea7ba1a90ed6f854af2101522be24e4efd7932 Mon Sep 17 00:00:00 2001 From: Vsevolod Pukhov Date: Mon, 15 Aug 2022 18:20:44 +0300 Subject: [PATCH] Fixes for ECMAScript runtime, napi Signed-off-by: Vsevolod Pukhov --- runtime/ecma_class_linker_extension.cpp | 2 +- runtime/intrinsics-inl.h | 5 +++ runtime/js_object.cpp | 8 +++++ runtime/mem/ecma_reference_processor.cpp | 6 ---- runtime/napi/include/jsnapi.h | 3 ++ runtime/napi/jsnapi.cpp | 44 +++++++++++++++++------- tests/runtime/common/module/module_a.js | 7 +++- tests/runtime/common/module/module_c.js | 13 +++++-- 8 files changed, 66 insertions(+), 22 deletions(-) diff --git a/runtime/ecma_class_linker_extension.cpp b/runtime/ecma_class_linker_extension.cpp index 768bc9f38..a3c021210 100644 --- a/runtime/ecma_class_linker_extension.cpp +++ b/runtime/ecma_class_linker_extension.cpp @@ -110,7 +110,7 @@ Class *EcmaClassLinkerExtension::NewClass(const uint8_t *descriptor, size_t vtab hclass_ptr->GetHClass()->SetNativeFieldMask(std::numeric_limits::max()); // All fields must be set before call SetClass to make TSAN happy. // The intstance of this HClass may be read by update remset thread. - // The thread skips the object if tits class is null. + // The thread skips the object if this class is null. hclass_ptr->SetClass(hclass_ptr); JSHandle klass_obj(vm_->GetJSThread(), factory->NewNonMovableDynObject(hclass)); diff --git a/runtime/intrinsics-inl.h b/runtime/intrinsics-inl.h index 247692b0f..aba490471 100644 --- a/runtime/intrinsics-inl.h +++ b/runtime/intrinsics-inl.h @@ -427,6 +427,11 @@ INLINE_ECMA_INTRINSICS uint64_t TryLdGlobalByName(JSThread *thread, uint32_t str #endif bool found = false; + result = SlowRuntimeStub::LdGlobalRecord(thread, prop, &found); + if (found) { + return PropertyBox::Cast(result.GetTaggedObject())->GetValue().GetRawData(); + } + result = FastRuntimeStub::GetGlobalOwnProperty(global_obj, prop, &found); if (found) { return result.GetRawData(); diff --git a/runtime/js_object.cpp b/runtime/js_object.cpp index 57e922705..3e749b2b3 100644 --- a/runtime/js_object.cpp +++ b/runtime/js_object.cpp @@ -1831,7 +1831,15 @@ JSHandle JSObject::CreateObjectFromProperties(const JSThread *thread, return obj; } JSHandle obj = factory->NewEmptyJSObject(); + JSHandle jshclass(thread, obj->GetJSHClass()); + uint32_t numberInlinedProps = jshclass->GetInlinedProperties(); JSHClass::TransitionToDictionary(thread, obj); + // trim in-obj properties space + if (numberInlinedProps > 0) { + uint32_t newSize = obj->GetClass()->GetObjectSize(); + size_t trimBytes = numberInlinedProps * JSTaggedValue::TaggedTypeSize(); + factory->FillFreeObject(ToUintPtr(*obj) + newSize, trimBytes, RemoveSlots::YES); + } JSMutableHandle dict( thread, NameDictionary::Create(thread, NameDictionary::ComputeHashTableSize(propsLen))); diff --git a/runtime/mem/ecma_reference_processor.cpp b/runtime/mem/ecma_reference_processor.cpp index 3bc1e35fa..5b652467b 100644 --- a/runtime/mem/ecma_reference_processor.cpp +++ b/runtime/mem/ecma_reference_processor.cpp @@ -72,12 +72,6 @@ bool EcmaReferenceProcessor::IsReference([[maybe_unused]] const BaseClass *base_ } ASSERT(ref->ClassAddr()->IsDynamicClass()); - static_assert(panda::ecmascript::JSHClass::GetHClassOffset() == panda::coretypes::Class::GetRuntimeClassOffset()); - auto *as_hcls = reinterpret_cast(ref); - if ((as_hcls->GetHClass()->GetFlags() & panda::Class::DYNAMIC_CLASSROOT) != 0) { - return false; - } - auto *hcls = panda::ecmascript::JSHClass::FromHClass(ref->ClassAddr()); if (!hcls->IsWeakContainer()) { return false; diff --git a/runtime/napi/include/jsnapi.h b/runtime/napi/include/jsnapi.h index 1da1a7915..8c20ba29d 100644 --- a/runtime/napi/include/jsnapi.h +++ b/runtime/napi/include/jsnapi.h @@ -868,7 +868,9 @@ public: static void DestroyJSVM(EcmaVM *ecmaVm); // JS code + static bool Execute(EcmaVM *vm, Local fileName, Local entry); static bool Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry); + static bool Execute(EcmaVM *vm, const uint8_t *data, int32_t size, Local entry); static bool Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry); static bool ExecuteModuleFromBuffer(EcmaVM *vm, const void *data, int32_t size, const std::string &file); static Local GetExportObject(EcmaVM *vm, const std::string &file, const std::string &itemName); @@ -882,6 +884,7 @@ public: // Exception static void ThrowException(const EcmaVM *vm, Local error); static Local GetUncaughtException(const EcmaVM *vm); + static Local GetAndClearUncaughtException(const EcmaVM *vm); static void EnableUserUncaughtErrorHandler(EcmaVM *vm); static bool StartDebugger(const char *library_path, EcmaVM *vm, bool isDebugMode); diff --git a/runtime/napi/jsnapi.cpp b/runtime/napi/jsnapi.cpp index 454a4edf2..e1462bb4b 100644 --- a/runtime/napi/jsnapi.cpp +++ b/runtime/napi/jsnapi.cpp @@ -91,7 +91,6 @@ using ecmascript::ObjectFactory; using ecmascript::OperationResult; using ecmascript::PromiseCapability; using ecmascript::PropertyDescriptor; -using ecmascript::Region; using ecmascript::TaggedArray; using ecmascript::base::BuiltinsBase; using ecmascript::base::JsonParser; @@ -275,6 +274,11 @@ bool JSNApi::StopDebugger([[maybe_unused]] const char *library_path) return true; } +bool JSNApi::Execute(EcmaVM *vm, Local fileName, Local entry) +{ + return Execute(vm, fileName->ToString(), entry->ToString()); +} + bool JSNApi::Execute(EcmaVM *vm, const std::string &fileName, const std::string &entry) { std::vector argv; @@ -287,6 +291,11 @@ bool JSNApi::Execute(EcmaVM *vm, const std::string &fileName, const std::string return true; } +bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size, Local entry) +{ + return Execute(vm, data, size, entry->ToString()); +} + bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::string &entry) { std::vector argv; @@ -298,6 +307,11 @@ bool JSNApi::Execute(EcmaVM *vm, const uint8_t *data, int32_t size, const std::s return true; } +Local JSNApi::GetAndClearUncaughtException(const EcmaVM *vm) +{ + return JSNApiHelper::ToLocal(vm->GetEcmaUncaughtException()); +} + Local JSNApi::GetUncaughtException(const EcmaVM *vm) { return JSNApiHelper::ToLocal(vm->GetEcmaUncaughtException()); @@ -308,6 +322,15 @@ void JSNApi::EnableUserUncaughtErrorHandler(EcmaVM *vm) return vm->EnableUserUncaughtErrorHandler(); } +[[maybe_unused]] static JSThread *GetCurrentThread() +{ + auto thread = Thread::GetCurrent(); + if (thread == nullptr || thread->GetThreadType() != Thread::ThreadType::THREAD_TYPE_MANAGED) { + LOG(FATAL, RUNTIME) << "Unexpected thread type"; + } + return JSThread::Cast(ManagedThread::CastFromThread(thread)); +} + Local JSNApi::GetGlobalObject(const EcmaVM *vm) { JSHandle globalEnv = vm->GetGlobalEnv(); @@ -945,7 +968,12 @@ Local FunctionRef::Call(const EcmaVM *vm, Local thisObj, } ScopedManagedCodeThread s(thread); JSHandle func = JSNApiHelper::ToJSHandle(this); - JSHandle thisValue = JSNApiHelper::ToJSHandle(thisObj); + JSHandle thisValue; + if (thisObj.IsEmpty()) { + thisValue = JSNApiHelper::ToJSHandle(thisObj); + } else { + thisValue = JSHandle(thread, thread->GlobalConstants()->GetUndefined()); + } ObjectFactory *factory = vm->GetFactory(); JSHandle arguments = factory->NewTaggedArray(length); Span> sp(argv, length); @@ -1517,11 +1545,7 @@ JSTaggedValue Callback::RegisterCallbackWithProperty(ecmascript::EcmaRuntimeCall } JSHandle extraInfo(extraInfoValue); // vm - Region *region = Region::ObjectAddressToRange(extraInfo.GetTaggedValue().GetTaggedObject()); - if (region == nullptr) { - return JSTaggedValue::False(); - } - EcmaVM *vm = region->GetHeap()->GetEcmaVM(); + EcmaVM *vm = thread->GetEcmaVM(); // data JSHandle data(thread, extraInfo->GetData()); if (!data->IsHeapObject()) { @@ -1567,11 +1591,7 @@ JSTaggedValue Callback::RegisterCallbackWithNewTarget(ecmascript::EcmaRuntimeCal } JSHandle extraInfo(extraInfoValue); // vm - Region *region = Region::ObjectAddressToRange(extraInfo.GetTaggedValue().GetTaggedObject()); - if (region == nullptr) { - return JSTaggedValue::False(); - } - EcmaVM *vm = region->GetHeap()->GetEcmaVM(); + EcmaVM *vm = thread->GetEcmaVM(); // data JSHandle data(thread, extraInfo->GetData()); if (!data->IsHeapObject()) { diff --git a/tests/runtime/common/module/module_a.js b/tests/runtime/common/module/module_a.js index 4754ea566..efc195680 100644 --- a/tests/runtime/common/module/module_a.js +++ b/tests/runtime/common/module/module_a.js @@ -1,5 +1,5 @@ import { Car } from 'module_b.abc'; // Test direct Export & use after import -import { Star } from 'module_c.abc'; // Test indirect Export & use after import +import { Star, myClass } from 'module_c.abc'; // Test indirect Export & use after import let A = Car; @@ -27,4 +27,9 @@ if (infoA != "HWCar_Test:HW_Test:CNY:XXW_Test" ) { print("Indirect Export Fail"); } else { print("Pass!!"); +} + +let myClassObj = new myClass(42); +if (myClassObj.x !== 42 || myClassObj.foo() !== 42) { + throw "bad myClass"; } \ No newline at end of file diff --git a/tests/runtime/common/module/module_c.js b/tests/runtime/common/module/module_c.js index df0c63350..c6c300ba4 100644 --- a/tests/runtime/common/module/module_c.js +++ b/tests/runtime/common/module/module_c.js @@ -1,10 +1,19 @@ var Star = { - starColor: function() { + starColor: function () { return this.name + ":" + this.type + ":" + this.color; } } -export { Star }; +class myClass { + constructor(val) { + this.x = val; + } + foo() { + return this.x; + } +}; + +export { Star, myClass }; var myStar = { name: "Polaris", -- Gitee