Files
ark_js_runtime/ecmascript/require/js_cjs_module.cpp
T
luochuhao d8e482f756 Modify enable logic of certain runtime options.
Change condtion for File execution branch to whether file is AOT compiled or not.

Fix bug of setting bc debug handler entry while loading stub file.

Issue: https://gitee.com/openharmony/ark_js_runtime/issues/I5BBFH
Signed-off-by: luochuhao <luochuhao@huawei.com>
Change-Id: I5b6d47a1587631849f6c1e746473cb14b1d727a8
2022-06-13 12:15:03 +08:00

189 lines
9.3 KiB
C++

/*
* Copyright (c) 2022 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.
*/
#include "js_cjs_module.h"
#include "ecmascript/interpreter/interpreter-inl.h"
#include "ecmascript/interpreter/slow_runtime_stub.h"
#include "ecmascript/require/js_cjs_module_cache.h"
#include "ecmascript/require/js_require_manager.h"
#include "ecmascript/jspandafile/js_pandafile.h"
#include "ecmascript/jspandafile/js_pandafile_executor.h"
#include "ecmascript/jspandafile/js_pandafile_manager.h"
namespace panda::ecmascript {
void JSCjsModule::InitializeModule(JSThread *thread, JSHandle<JSCjsModule> &module,
JSHandle<JSTaggedValue> &filename, JSHandle<JSTaggedValue> &dirname)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
JSHandle<JSTaggedValue> dirKey(factory->NewFromASCII("path"));
SlowRuntimeStub::StObjByName(thread, module.GetTaggedValue(), dirKey.GetTaggedValue(),
dirname.GetTaggedValue());
JSHandle<JSTaggedValue> filenameKey(factory->NewFromASCII("filename"));
SlowRuntimeStub::StObjByName(thread, module.GetTaggedValue(), filenameKey.GetTaggedValue(),
filename.GetTaggedValue());
module->SetFilename(thread, filename.GetTaggedValue());
module->SetPath(thread, dirname.GetTaggedValue());
return;
}
JSHandle<JSTaggedValue> JSCjsModule::SearchFromModuleCache(JSThread *thread, JSHandle<JSTaggedValue> &filename)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
JSHandle<JSTaggedValue> moduleObj(env->GetCjsModuleFunction());
JSHandle<JSTaggedValue> cacheName = globalConst->GetHandledCjsCacheString();
JSTaggedValue modCache = SlowRuntimeStub::LdObjByName(thread, moduleObj.GetTaggedValue(),
cacheName.GetTaggedValue(),
false,
JSTaggedValue::Undefined());
JSHandle<CjsModuleCache> moduleCache = JSHandle<CjsModuleCache>(thread, modCache);
if (moduleCache->ContainsModule(filename.GetTaggedValue())) {
JSHandle<JSCjsModule> cachedModule = JSHandle<JSCjsModule>(thread,
moduleCache->GetModule(filename.GetTaggedValue()));
JSHandle<JSTaggedValue> exportsName = globalConst->GetHandledCjsExportsString();
JSTaggedValue cachedExports = SlowRuntimeStub::LdObjByName(thread, cachedModule.GetTaggedValue(),
exportsName.GetTaggedValue(),
false,
JSTaggedValue::Undefined());
return JSHandle<JSTaggedValue>(thread, cachedExports);
}
return JSHandle<JSTaggedValue>(thread, JSTaggedValue::Hole());
}
void JSCjsModule::PutIntoCache(JSThread *thread, JSHandle<JSCjsModule> &module, JSHandle<JSTaggedValue> &filename)
{
JSHandle<GlobalEnv> env = thread->GetEcmaVM()->GetGlobalEnv();
const GlobalEnvConstants *globalConst = thread->GlobalConstants();
JSHandle<JSTaggedValue> moduleObj(env->GetCjsModuleFunction());
JSHandle<JSTaggedValue> cacheName = globalConst->GetHandledCjsCacheString();
JSTaggedValue modCache = SlowRuntimeStub::LdObjByName(thread, moduleObj.GetTaggedValue(),
cacheName.GetTaggedValue(),
false,
JSTaggedValue::Undefined());
JSHandle<CjsModuleCache> moduleCache = JSHandle<CjsModuleCache>(thread, modCache);
JSHandle<JSTaggedValue> moduleHandle = JSHandle<JSTaggedValue>::Cast(module);
JSHandle<CjsModuleCache> newCache = CjsModuleCache::PutIfAbsent(thread, moduleCache, filename,
moduleHandle);
SlowRuntimeStub::StObjByName(thread, moduleObj.GetTaggedValue(), cacheName.GetTaggedValue(),
newCache.GetTaggedValue());
}
JSHandle<JSTaggedValue> JSCjsModule::Load(JSThread *thread, JSHandle<EcmaString> &request)
{
[[maybe_unused]] EcmaHandleScope handleScope(thread);
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
// Get local jsPandaFile's dirPath
JSMutableHandle<JSTaggedValue> parent(thread, JSTaggedValue::Undefined());
JSMutableHandle<JSTaggedValue> dirname(thread, JSTaggedValue::Undefined());
const JSPandaFile *jsPandaFile = EcmaInterpreter::GetNativeCallPandafile(thread);
JSRequireManager::ResolveCurrentPath(thread, parent, dirname, jsPandaFile);
// Get filename from Callback
JSHandle<EcmaString> filenameStr = ResolveFilename(thread, dirname.GetTaggedValue(),
request.GetTaggedValue());
JSHandle<JSTaggedValue> filename = JSHandle<JSTaggedValue>::Cast(filenameStr);
// Search from Module.cache
JSHandle<JSTaggedValue> maybeCachedExports = SearchFromModuleCache(thread, filename);
if (!maybeCachedExports->IsHole()) {
return maybeCachedExports;
}
// Don't get required exports from cache, execute required JSPandaFile.
// module = new Module(), which belongs to required JSPandaFile.
JSHandle<JSCjsModule> module = factory->NewCjsModule();
InitializeModule(thread, module, filename, dirname);
PutIntoCache(thread, module, filename);
// Execute required JSPandaFile
RequireExecution(thread, JSHandle<EcmaString>::Cast(filename));
// Search from Module.cache after execution.
JSHandle<JSTaggedValue> cachedExports = SearchFromModuleCache(thread, filename);
if (cachedExports->IsHole()) {
LOG_ECMA(ERROR) << "CJS REQUIRE FAIL : Can not obtain module, after executing required jsPandaFile";
UNREACHABLE();
}
return cachedExports;
}
void JSCjsModule::RequireExecution(JSThread *thread, const JSHandle<EcmaString> &moduleFileName)
{
CString moduleFilenameStr = ConvertToString(moduleFileName.GetTaggedValue());
const JSPandaFile *jsPandaFile =
JSPandaFileManager::GetInstance()->LoadJSPandaFile(thread, moduleFilenameStr, JSPandaFile::ENTRY_MAIN_FUNCTION);
if (jsPandaFile == nullptr) {
LOG_ECMA(ERROR) << "open jsPandaFile " << moduleFilenameStr << " error";
UNREACHABLE();
}
JSPandaFileExecutor::Execute(thread, jsPandaFile);
}
JSHandle<EcmaString> JSCjsModule::ResolveFilename(JSThread *thread, JSTaggedValue dirname, JSTaggedValue request)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
ResolvePathCallback resolvePathCallback = thread->GetEcmaVM()->GetResolvePathCallback();
if (resolvePathCallback == nullptr) {
JSHandle<EcmaString> nativeRequireName = ResolveFilenameFromNative(thread, dirname, request);
return nativeRequireName;
}
std::string modDirname = std::string(ConvertToString(EcmaString::Cast(dirname.GetHeapObject())));
std::string modFile = std::string(ConvertToString(EcmaString::Cast(request.GetHeapObject())));
std::string callbackRequireName = resolvePathCallback(modDirname, modFile);
CString fullname = callbackRequireName.c_str();
return factory->NewFromUtf8(fullname);
}
JSHandle<EcmaString> JSCjsModule::ResolveFilenameFromNative(JSThread *thread, JSTaggedValue dirname,
JSTaggedValue request)
{
ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
CString dirnameStr = ConvertToString(EcmaString::Cast(dirname.GetHeapObject()));
CString requestStr = ConvertToString(EcmaString::Cast(request.GetHeapObject()));
if (requestStr.find("./") == 0) {
requestStr = requestStr.substr(2); // 2 : delete './'
}
int suffixEnd = static_cast<int>(requestStr.find_last_of('.'));
if (suffixEnd == -1) {
RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
}
CString fullname;
if (requestStr[0] == '/') { // absolute FilePath
fullname = requestStr.substr(0, suffixEnd) + ".abc";
} else {
int pos = static_cast<int>(dirnameStr.find_last_of('/'));
if (pos == -1) {
RETURN_HANDLE_IF_ABRUPT_COMPLETION(EcmaString, thread);
}
fullname = dirnameStr.substr(0, pos + 1) + requestStr.substr(0, suffixEnd) + ".abc";
}
return factory->NewFromUtf8(fullname);
}
JSTaggedValue JSCjsModule::Require(JSThread *thread, JSHandle<EcmaString> &request,
[[maybe_unused]]JSHandle<JSCjsModule> &parent,
[[maybe_unused]]bool isMain)
{
Load(thread, request);
return JSTaggedValue::Undefined();
}
} // namespace panda::ecmascript