/* * Tencent is pleased to support the open source community by making ScriptX available. * Copyright (C) 2021 THL A29 Limited, a Tencent company. All rights reserved. * * 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 "WasmEngine.h" #include "../../src/Native.hpp" #include "../../src/Reference.h" #include "../../src/Utils.h" #include "WasmNative.hpp" #include "WasmReference.hpp" #include "WasmScope.hpp" #include "../../src/utils/Helper.hpp" namespace script::wasm_backend { WasmEngine::WasmEngine() { engineThreadId_ = std::this_thread::get_id(); } WasmEngine* WasmEngine::instance() { static WasmEngine engine; return &engine; } WasmEngine::~WasmEngine() = default; void WasmEngine::ignoreDestroyCall() { instance()->ignoreDestroyCall_ = true; } void WasmEngine::destroy() { if (!ignoreDestroyCall_) { throw Exception( "WasmEngine is a Singleton, thus can't be destroyed. " "To suppress this exception, please opt-in with WasmEngine::ignoreDestroyCall()"); } } bool WasmEngine::isDestroying() const { return false; } void WasmEngine::unitTestResetRegistry() { classDefineRegistry_.clear(); ScriptEngine::classDefineRegistry_.clear(); } void WasmEngine::doDeleteScriptClass(ScriptClass* scriptClass) { delete scriptClass; } Local WasmEngine::getGlobal() const { return Local(Stack::getGlobal()); } Local WasmEngine::get(const Local& key) { return Local(Stack::globalGet(key.val_)); } void WasmEngine::set(const Local& key, const Local& value) { Stack::globalSet(key.val_, value.val_); } Local WasmEngine::eval(const Local& script) { return eval(script, Local()); } Local WasmEngine::eval(const Local& script, const Local& sourceFile) { return eval(script, sourceFile.asValue()); } Local WasmEngine::eval(const Local& script, const Local& sourceFile) { Tracer trace(this, "WasmEngine::eval"); auto retIndex = evaluateJavaScriptCode(script.val_, sourceFile.val_); return Local(retIndex); } Local WasmEngine::loadFile(const Local& scriptFile) { if(scriptFile.toString().empty()) throw Exception("script file no found"); Local content = internal::readAllFileContent(scriptFile); if(content.isNull()) throw Exception("can't load script file"); std::string sourceFilePath = scriptFile.toString(); std::size_t pathSymbol = sourceFilePath.rfind("/"); if(pathSymbol != -1) sourceFilePath = sourceFilePath.substr(pathSymbol + 1); else { pathSymbol = sourceFilePath.rfind("\\"); if(pathSymbol != -1) sourceFilePath = sourceFilePath.substr(pathSymbol + 1); } Local sourceFileName = String::newString(sourceFilePath); return eval(content.asString(), sourceFileName); } std::shared_ptr WasmEngine::messageQueue() { return messageQueue_; } void WasmEngine::gc() {} void WasmEngine::adjustAssociatedMemory(int64_t count) {} ScriptLanguage WasmEngine::getLanguageType() { return ScriptLanguage::kJavaScript; } std::string WasmEngine::getEngineVersion() { return "WebAssemble"; } void WasmEngine::defineStatic(const Local& obj, const internal::StaticDefine& define) { for (auto&& func : define.functions) { StackFrameScope stackFrame; auto fi = Stack::newFunction( [](const Arguments& args, void* data, void*) -> Local { auto fun = static_cast(data); Tracer trace(args.engineAs(), fun->traceName); return fun->callback(args); }, &func); obj.set(func.name, Local(fi)); } for (auto&& prop : define.properties) { StackFrameScope stackFrame; int getter = -1; int setter = -1; auto name = String::newString(prop.name); if (prop.getter) { getter = Stack::newFunction( [](const Arguments& args, void* data, void*) -> Local { auto pro = static_cast(data); Tracer trace(args.engine(), pro->traceName); return pro->getter(); }, &prop); } if (prop.setter) { setter = Stack::newFunction( [](const Arguments& args, void* data, void*) -> Local { auto pro = static_cast(data); Tracer trace(args.engine(), pro->traceName); pro->setter(args[0]); return {}; }, &prop); } NativeHelper::defineProperty(obj.val_, name.val_, getter, setter); } } void* WasmEngine::verifyAndGetInstance(const void* classDefine, int thiz) { auto ins = NativeHelper::getInternalStateInstance(thiz); auto define = NativeHelper::getInternalStateClassDefine(thiz); if (ins == nullptr || define != classDefine) { throw Exception("call Instance Function on wrong instance"); } return ins; } Local WasmEngine::getNamespaceForRegister(const std::string_view& nameSpace) { StackFrameScope scope; auto ret = NativeHelper::getNamespaceForRegister(String::newString(nameSpace).val_); if (ret == -1) { throw Exception("can't get namespace for:" + std::string(nameSpace)); } return scope.returnValue(Local(ret).asObject()); } } // namespace script::wasm_backend