/* * 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. */ #pragma once #include #include #include #include #include "../../src/Engine.h" #include "../../src/Exception.h" #include "../../src/Scope.h" #include "../../src/utils/MessageQueue.h" #include "WasmHelper.h" namespace script::test { class ScriptXTestFixture; } namespace script::wasm_backend { class WasmEngine : public ScriptEngine { // < classDefine, Class > std::unordered_map> classDefineRegistry_{}; std::shared_ptr messageQueue_ = std::make_shared(); bool ignoreDestroyCall_ = false; std::thread::id engineThreadId_ = {}; WasmEngine(); // for unit-test only void unitTestResetRegistry(); public: static WasmEngine* instance(); SCRIPTX_DISALLOW_COPY_AND_MOVE(WasmEngine); /** * WasmEngine can't be destroyed. * So the default implementation is to throw exception. * By WasmEngine::ignoreDestroyCall, change the behavior to ignore, and don't throw. */ static void ignoreDestroyCall(); void destroy() override; bool isDestroying() const override; Local getGlobal() const; Local get(const Local& key) override; void set(const Local& key, const Local& value) override; using ScriptEngine::set; Local eval(const Local& script, const Local& sourceFile); Local eval(const Local& script, const Local& sourceFile) override; Local eval(const Local& script) override; using ScriptEngine::eval; Local loadFile(const Local& scriptFile) override; std::shared_ptr messageQueue() override; void gc() override; void adjustAssociatedMemory(int64_t count) override; ScriptLanguage getLanguageType() override; std::string getEngineVersion() override; protected: ~WasmEngine() override; private: template void registerNativeClassImpl(const ClassDefine* classDefine); template Local newConstructor(const ClassDefine* classDefine); template void defineInstance(const ClassDefine* classDefine, const Local& obj); static Local getNamespaceForRegister(const std::string_view& nameSpace); void defineStatic(const Local& obj, const internal::StaticDefine& define); static void* verifyAndGetInstance(const void* classDefine, int thiz); template Local newNativeClassImpl(const ClassDefine* classDefine, size_t size, const Local* args); template bool isInstanceOfImpl(const Local& value, const ClassDefine* classDefine); template T* getNativeInstanceImpl(const Local& value, const ClassDefine* classDefine); private: // helpers template static auto&& refIndex(const Local& ref) { return ref.val_; } template static int refIndex(const Weak& ref) { return ref.val_; } template static T make(Args&&... args) { return T(std::forward(args)...); } friend class ::script::ScriptEngine; friend class ::script::ScriptClass; friend class ::script::Exception; friend class ::script::Object; friend class ::script::Arguments; friend class Stack; friend class WasmEngineScope; friend class WasmStackFrameScope; friend struct ::script::wasm_interop; friend class ByteBufferHelper; friend Local callFunction(const Local& func, const Local& thiz, size_t size, const Local* args); friend void invokeFunctionHelper(Stack::RawFunctionType func, void* ptr0, void* ptr1, int stackBase, WasmEngine* engine); static void doDeleteScriptClass(ScriptClass* scriptClass); friend void deleteScriptClassHelper(ScriptClass* scriptClass); friend WasmEngine& currentEngine(); // UnitTest friend class ::script::test::ScriptXTestFixture; }; } // namespace script::wasm_backend