/* * 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 "../../src/Engine.h" #include "../../src/Native.h" #include "../../src/utils/GlobalWeakBookkeeping.hpp" #include "JscHelper.h" namespace script::internal { // forward declare // defined in JscEngine.h template struct MakeLocalHelper; } // namespace script::internal namespace script::jsc_backend { class JscEngine : public ::script::ScriptEngine { struct ClassRegistryData { JSClassRef instanceClass{}; Global constructor{}; Global prototype{}; }; std::shared_ptr messageQueue_; std::unordered_map classRegistry_; std::unordered_map> keptReference_; internal::GlobalWeakBookkeeping globalWeakBookkeeping_; size_t keepId_ = 0; bool isDestroying_ = false; static JSClassRef globalClass_; static JSClassRef externalClass_; // >= ios10, >= macOS 10.12 static bool hasByteBufferAPI_; protected: std::shared_ptr virtualMachineLock_ = std::make_shared(); JSContextGroupRef virtualMachine_ = nullptr; JSGlobalContextRef context_ = nullptr; Global internalStorageSymbol_; Global constructorMarkSymbol_; Global getInternalStorageBySymbolFunction_; Global isByteBuffer_; private: static void checkException(JSValueRef exception); public: explicit JscEngine(std::shared_ptr messageQueue = {}); void destroy() noexcept override; bool isDestroying() const override { return isDestroying_; } Local getGlobal(); 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) 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: ~JscEngine() override; private: Local eval(const Local& script, const Local& sourceFile); template bool registerNativeClassImpl(const ClassDefine* classDefine); 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: template static inline typename RefTypeMap::jscType toJsc(JSGlobalContextRef /*context*/, const Local& ref) { return ref.val_; } static inline typename RefTypeMap::jscType toJsc(JSGlobalContextRef context, const Local& ref) { return ref.val_.getValue(context); } static typename RefTypeMap::jscType toJsc(JSGlobalContextRef context, const Local& ref); static Arguments newArguments(JscEngine* engine, JSObjectRef thisObject, const JSValueRef* arguments, size_t size); template static T make(Args&&... args) { return T(std::forward(args)...); } Local newStaticFunction(const internal::StaticDefine::FunctionDefine& func); Local newStaticGetter(const internal::StaticDefine::PropertyDefine& prop); Local newStaticSetter(const internal::StaticDefine::PropertyDefine& prop); void registerStaticDefine(const internal::StaticDefine& staticDefine, const Local& object); template void defineInstance(const ClassDefine* classDefine, Local& object, ClassRegistryData& registry); template JSObjectCallAsConstructorCallback createConstructor(); template Local defineInstancePrototype(const ClassDefine* classDefine); template void defineInstanceFunction(const ClassDefine* classDefine, Local& prototypeObject); template void defineInstanceProperties(const ClassDefine* classDefine, ConsumeLambda consumerLambda); size_t keepReference(const Local& ref); void removeKeptReference(size_t id); void initInternalSymbols(); bool isConstructorMarkSymbol(JSValueRef value); private: template friend class ::script::Local; template friend class ::script::Global; template friend class ::script::Weak; friend class ::script::Object; friend class ::script::Array; friend class ::script::Function; friend class ::script::ByteBuffer; friend class ::script::ScriptEngine; friend class ::script::Exception; friend class ::script::Arguments; friend class ::script::ScriptClass; friend class JscStringRefHolder; friend class JscWeakRef; friend JSGlobalContextRef currentEngineContextChecked(); friend JSContextGroupRef currentEngineContextGroupChecked(); friend class JscEngineScope; friend class JscExitEngineScope; friend class StringLocalRef; friend struct JscBookKeepFetcher; template friend R toJscValues(JSGlobalContextRef context, size_t length, const Local* args, Fn fn); friend JSObjectRef valueToObj(JSGlobalContextRef context, JSValueRef value); friend struct ::script::jsc_interop; template friend struct ::script::internal::MakeLocalHelper; template static auto& refVal(Ref* ref) { return ref->val_; } }; } // namespace script::jsc_backend