!10331 修复Lazy import场景下,异步任务执行时序不对的问题

Merge pull request !10331 from wangchen/LdLazyModuleVar
This commit is contained in:
openharmony_ci 2024-11-22 10:21:49 +00:00 committed by Gitee
commit 973daf8287
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 160 additions and 9 deletions

View File

@ -124,6 +124,23 @@ public:
bool ExecutePromisePendingJob();
bool IsInPendingJob() const
{
return pendingJobEnterCount > 0;
}
void AddPendingJobEnterCount()
{
ASSERT(pendingJobEnterCount < std::numeric_limits<uint64_t>::max());
++pendingJobEnterCount;
}
void MinusPendingJobEnterCount()
{
ASSERT(IsInPendingJob());
--pendingJobEnterCount;
}
static EcmaContext *ConstCast(const EcmaContext *context)
{
return const_cast<EcmaContext *>(context);
@ -780,6 +797,8 @@ private:
bool hasKeptObjects_ {false};
uint64_t pendingJobEnterCount {0};
friend class EcmaHandleScope;
friend class JSPandaFileExecutor;
friend class ObjectFactory;

View File

@ -20,8 +20,19 @@
#include "ecmascript/js_tagged_value-inl.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tagged_queue.h"
#include "ecmascript/ecma_context.h"
namespace panda::ecmascript::job {
MicroJobScope::MicroJobScope(JSThread* thread) : thread_(thread)
{
thread_->GetCurrentEcmaContext()->AddPendingJobEnterCount();
}
MicroJobScope::~MicroJobScope()
{
thread_->GetCurrentEcmaContext()->MinusPendingJobEnterCount();
}
uint32_t MicroJobQueue::GetPromiseQueueSize(JSThread *thread, JSHandle<MicroJobQueue> jobQueue)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
@ -58,6 +69,7 @@ void MicroJobQueue::EnqueueJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueu
void MicroJobQueue::ExecutePendingJob(JSThread *thread, JSHandle<MicroJobQueue> jobQueue)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
[[maybe_unused]] MicroJobScope microJobScope(thread);
JSMutableHandle<TaggedQueue> promiseQueue(thread, jobQueue->GetPromiseJobQueue());
JSMutableHandle<PendingJob> pendingJob(thread, JSTaggedValue::Undefined());
while (!promiseQueue->Empty()) {

View File

@ -23,7 +23,13 @@
#include "ecmascript/tagged_array.h"
namespace panda::ecmascript::job {
class MicroJobScope {
public:
explicit MicroJobScope(JSThread *thread);
~MicroJobScope();
private:
JSThread *thread_;
};
class MicroJobQueue final : public Record {
public:
static MicroJobQueue *Cast(TaggedObject *object)

View File

@ -181,7 +181,7 @@ JSTaggedValue ModuleManager::GetLazyModuleValueOutterInternal(int32_t index, JST
if (resolvedBinding.IsResolvedIndexBinding()) {
JSHandle<ResolvedIndexBinding> binding(thread, resolvedBinding);
JSTaggedValue resolvedModule = binding->GetModule();
JSHandle<SourceTextModule> module(thread, resolvedModule);
JSMutableHandle<SourceTextModule> module(thread, resolvedModule);
ASSERT(resolvedModule.IsSourceTextModule());
// Support for only modifying var value of HotReload.
// Cause patchFile exclude the record of importing modifying var. Can't reresolve moduleRecord.
@ -191,13 +191,12 @@ JSTaggedValue ModuleManager::GetLazyModuleValueOutterInternal(int32_t index, JST
context->FindPatchModule(module->GetEcmaModuleRecordNameString());
if (!resolvedModuleOfHotReload->IsHole()) {
resolvedModule = resolvedModuleOfHotReload.GetTaggedValue();
JSHandle<SourceTextModule> moduleOfHotReload(thread, resolvedModule);
SourceTextModule::Evaluate(thread, moduleOfHotReload, nullptr);
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
return ModuleManagerHelper::GetModuleValue(thread, moduleOfHotReload, binding->GetIndex());
module.Update(resolvedModule);
}
}
SourceTextModule::Evaluate(thread, module, nullptr);
if (module->GetStatus() != ModuleStatus::EVALUATED) {
SourceTextModule::Evaluate(thread, module, nullptr, 0, context->IsInPendingJob());
}
RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Exception());
return ModuleManagerHelper::GetModuleValue(thread, module, binding->GetIndex());
}

View File

@ -0,0 +1,60 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @tc.name:asyncUseLazyImport
* @tc.desc:test asyncUseLazyImport
* @tc.type: FUNC
* @tc.require: issue#IB2HNC
*/
// @ts-nocheck
import lazy { TestLazy } from './lazyExport';
export class Test {
async start() {
this.log(` Test start`)
let a = await this.mapAsync([1, 2], async (t) => {
await this.bindRawData(t)
})
this.log(` Test end ${new Error().stack}`)
return a
}
private async bindRawData(t: number) {
await this.mapAsync([1, 2], async (k, b) => {
this.onBindRawData(t, k)
})
await this.mapAsync([4, 5], async (k, b) => {
this.onBindRawData(t, k)
})
await this.mapAsync([7, 8], async (k, b) => {
this.onBindRawData(t, k)
})
}
async mapAsync<T, U>(array: T[], map: (t: T, index: number) => Promise<U>) {
return await Promise.all(array.map(map))
}
private async onBindRawData(t: number, k: number) {
this.log(` onBindRawData start ${t} ${k}`)
await this.isSelf()
this.log(` onBindRawData end ${t} ${k}`)
}
private async isSelf(): Promise<boolean> {
return "1" == "1"
}
log(msg: string) {
TestLazy
print(msg)
}
}

View File

@ -30,3 +30,30 @@ this is dynamicLazySequence
this is dynamicSubFile
this is dynamicLazySequence2
dynamicSubFile
Test start
onBindRawData start 1 1
onBindRawData start 1 2
onBindRawData start 2 1
onBindRawData start 2 2
onBindRawData end 1 1
onBindRawData end 1 2
onBindRawData end 2 1
onBindRawData end 2 2
onBindRawData start 1 4
onBindRawData start 1 5
onBindRawData start 2 4
onBindRawData start 2 5
onBindRawData end 1 4
onBindRawData end 1 5
onBindRawData end 2 4
onBindRawData end 2 5
onBindRawData start 1 7
onBindRawData start 1 8
onBindRawData start 2 7
onBindRawData start 2 8
onBindRawData end 1 7
onBindRawData end 1 8
onBindRawData end 2 7
onBindRawData end 2 8
Test end at start (asyncUseLazyImport.ts:31:1)

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* @tc.name:asyncUseLazyImport
* @tc.desc:test asyncUseLazyImport
* @tc.type: FUNC
* @tc.require: issue#IB2HNC
*/
// @ts-nocheck
export class TestLazy {}

View File

@ -25,6 +25,7 @@ import { aaa } from "./E"
import lazy {func1} from './F'
import lazy {dynamicLazySequence} from './dynamicLazySequence'
import lazy {dynamicLazySequence2} from './dynamicLazySequence2'
import {Test} from './asyncUseLazyImport'
print("this is entry");
func1();
@ -36,3 +37,4 @@ import("./dynamicLazySequence").then((ns) => {
print(ns.dynamicLazySequence);
})
import("./dynamicLazySequence2");
new Test().start()

View File

@ -10,3 +10,5 @@ dynamicLazySequence.js;dynamicLazySequence;esm;dynamicLazySequence.js;xxdynamicL
dynamicLazySequence2.js;dynamicLazySequence2;esm;dynamicLazySequence2.js;xxdynamicLazySequence2xx
dynamicSubFile.js;dynamicSubFile;esm;dynamicSubFile.js;xxdynamicSubFilexx
moduleLazyImport.js;moduleLazyImport;esm;moduleLazyImport.js;xxmoduleLazyImportxx
asyncUseLazyImport.ts;asyncUseLazyImport;esm;asyncUseLazyImport.ts;xxasyncUseLazyImportxx
lazyExport.js;lazyExport;esm;lazyExport.js;xxlazyExportxx