//模拟node官方的toString方法 static Handle<Value> Buffer_toString (const Arguments &args) { HandleScope scope; Local<Object> buf = args.This(); int has_buf = buf->GetHiddenValue(String::New("isBuffer"))->Int32Value(); if(has_buf){ return scope.Close(buf->GetHiddenValue(String::New("buffer"))->ToString()); } else{ return scope.Close(Undefined()); } }
Handle<Value> TiRootObject::_require(void* userContext, TiObject* caller, const Arguments& args) { HandleScope scope; Local<Object> globalObject = TitaniumRuntime::getContenxt()->Global(); Handle<Value> nativeModule = TiModuleRegistry::GetModule(QString(*String::Utf8Value(args[0]->ToString()))); if(!nativeModule->IsUndefined()) { return scope.Close(nativeModule); } QString fileName = Ti::TiHelper::QStringFromValue(args[0]).append(".js"); QString filePath = Ti::TiHelper::getAssetPath(fileName).prepend("app/native/"); Local<Value> existingModule = globalObject->GetHiddenValue(Ti::TiHelper::ValueFromQString(fileName)->ToString()); if(!existingModule.IsEmpty() && !existingModule->IsUndefined()) { return scope.Close(existingModule); } QString js = readJsFile(filePath); if(js.isEmpty()) { ThrowException(String::New( QString("Module not found ").append(fileName).toLocal8Bit().constData() )); return scope.Close(Undefined()); } js.prepend("(function(){" "var __vars = {};" "__vars.exports = {};" "__vars.module = {exports:__vars.exports};" "var module = __vars.module;" "var exports = __vars.exports;"); js.append("\nreturn __vars.module.exports;" "})();"); Handle<Script> script = Script::Compile(Ti::TiHelper::ValueFromQString(js)->ToString() , Ti::TiHelper::ValueFromQString(fileName)); TryCatch tryCatch; if (script.IsEmpty()) { Ti::TiErrorScreen::ShowWithTryCatch(tryCatch); return scope.Close(Undefined()); } Persistent<Value> result = Persistent<Value>::New(script->Run()); result.MarkIndependent(); if (result.IsEmpty()) { Ti::TiErrorScreen::ShowWithTryCatch(tryCatch); return scope.Close(Undefined()); } globalObject->SetHiddenValue(Ti::TiHelper::ValueFromQString(fileName)->ToString(), result); return scope.Close(result); }
Local<Object> MetadataNode::GetImplementationObject(const Local<Object>& object) { DEBUG_WRITE("GetImplementationObject called on object:%d", object->GetIdentityHash()); auto target = object; Local<Value> currentPrototype = target; Local<Object> implementationObject; implementationObject = object->GetHiddenValue(ConvertToV8String("t::implObj")).As<Object>(); if (!implementationObject.IsEmpty()) { return implementationObject; } if (object->HasOwnProperty(V8StringConstants::GetIsPrototypeImplementationObject())) { auto v8Prototype = V8StringConstants::GetPrototype(); if (!object->HasOwnProperty(v8Prototype)) { return Local<Object>(); } DEBUG_WRITE("GetImplementationObject returning the prototype of the object :%d", object->GetIdentityHash()); return object->Get(v8Prototype).As<Object>(); } auto obj = V8GetHiddenValue(object, "t::ActivityImplementationObject").As<Object>(); if (!obj.IsEmpty()) { DEBUG_WRITE("GetImplementationObject returning ActivityImplementationObject property on object: %d", object->GetIdentityHash()); return obj; } Local<Value> lastPrototype; bool prototypeCycleDetected = false; while (implementationObject.IsEmpty()) { // currentPrototype = currentPrototype.As<Object>()->GetPrototype(); if (currentPrototype->IsNull()) break; //DEBUG_WRITE("GetImplementationObject currentPrototypeObject:%d", (currentPrototype.IsEmpty() || currentPrototype.As<Object>().IsEmpty()) ? -1 : currentPrototype.As<Object>()->GetIdentityHash()); //DEBUG_WRITE("GetImplementationObject lastPrototypeObject:%d", (lastPrototype.IsEmpty() || lastPrototype.As<Object>().IsEmpty()) ? -1 : lastPrototype.As<Object>()->GetIdentityHash()); if (currentPrototype == lastPrototype) { auto abovePrototype = currentPrototype.As<Object>()->GetPrototype(); prototypeCycleDetected = abovePrototype == currentPrototype; } if (currentPrototype.IsEmpty() || prototypeCycleDetected) { //Local<Value> abovePrototype = currentPrototype.As<Object>()->GetPrototype(); //DEBUG_WRITE("GetImplementationObject not found since cycle parents reached abovePrototype:%d", (abovePrototype.IsEmpty() || abovePrototype.As<Object>().IsEmpty()) ? -1 : abovePrototype.As<Object>()->GetIdentityHash()); return Local<Object>(); } else { auto value = currentPrototype.As<Object>()->GetHiddenValue(V8StringConstants::GetClassImplementationObject()); if (!value.IsEmpty()) { implementationObject = currentPrototype.As<Object>(); } } lastPrototype = currentPrototype; } return implementationObject; }
void MetadataNode::ExtendCallMethodHandler(const v8::FunctionCallbackInfo<v8::Value>& info) { if (info.IsConstructCall()) { string exMsg("Cannot call 'extend' as constructor"); ExceptionUtil::GetInstance()->ThrowExceptionToJs(exMsg); return; } SET_PROFILER_FRAME(); Local<Object> implementationObject; Local<String> extendName; string extendLocation; auto validArgs = ValidateExtendArguments(info, extendLocation, extendName, implementationObject); if (!validArgs) return; auto node = reinterpret_cast<MetadataNode*>(info.Data().As<External>()->Value()); DEBUG_WRITE("ExtendsCallMethodHandler: called with %s", ConvertToString(extendName).c_str()); string extendNameAndLocation = extendLocation + ConvertToString(extendName); auto fullClassName = TNS_PREFIX + CreateFullClassName(node->m_name, extendNameAndLocation); // //resolve class (pre-generated or generated runtime from dex generator) jclass resolvedClass = NativeScriptRuntime::ResolveClass(fullClassName, implementationObject); //resolve class returns GlobalRef std::string generatedFullClassName = s_objectManager->GetClassName(resolvedClass); // auto fullExtendedName = generatedFullClassName; DEBUG_WRITE("ExtendsCallMethodHandler: extend full name %s", fullClassName.c_str()); auto isolate = info.GetIsolate(); auto cachedData = GetCachedExtendedClassData(isolate, fullExtendedName); if (cachedData.extendedCtorFunction != nullptr) { auto cachedExtendedCtorFunc = Local<Function>::New(isolate, *cachedData.extendedCtorFunction); info.GetReturnValue().Set(cachedExtendedCtorFunc); return; } auto implementationObjectPropertyName = V8StringConstants::GetClassImplementationObject(); //reuse validation - checks that implementationObject is not reused for different classes auto implementationObjectProperty = implementationObject->GetHiddenValue(implementationObjectPropertyName).As<String>(); if (implementationObjectProperty.IsEmpty()) { //mark the implementationObject as such and set a pointer to it's class node inside it for reuse validation later implementationObject->SetHiddenValue(implementationObjectPropertyName, String::NewFromUtf8(isolate, fullExtendedName.c_str())); } else { string usedClassName = ConvertToString(implementationObjectProperty); stringstream s; s << "This object is used to extend another class '" << usedClassName << "'"; ExceptionUtil::GetInstance()->ThrowExceptionToJs(s.str()); return; } auto baseClassCtorFunc = node->GetConstructorFunction(isolate); auto extendData = External::New(isolate, new ExtendedClassData(node, extendNameAndLocation, implementationObject, fullExtendedName)); auto extendFuncTemplate = FunctionTemplate::New(isolate, ExtendedClassConstructorCallback, extendData); extendFuncTemplate->InstanceTemplate()->SetInternalFieldCount(static_cast<int>(ObjectManager::MetadataNodeKeys::END)); auto extendFunc = extendFuncTemplate->GetFunction(); auto prototypeName = ConvertToV8String("prototype"); implementationObject->SetPrototype(baseClassCtorFunc->Get(prototypeName)); implementationObject->SetAccessor(ConvertToV8String("super"), SuperAccessorGetterCallback, nullptr, implementationObject); auto extendFuncPrototype = extendFunc->Get(prototypeName).As<Object>(); auto p = extendFuncPrototype->GetPrototype(); extendFuncPrototype->SetPrototype(implementationObject); extendFunc->SetPrototype(baseClassCtorFunc); SetClassAccessor(extendFunc); SetTypeMetadata(isolate, extendFunc, new TypeMetadata(fullExtendedName)); info.GetReturnValue().Set(extendFunc); s_name2NodeCache.insert(make_pair(fullExtendedName, node)); ExtendedClassCacheData cacheData(extendFunc, fullExtendedName, node); s_extendedCtorFuncCache.insert(make_pair(fullExtendedName, cacheData)); }
void rtNodeContext::clonedEnvironment(rtNodeContextRef clone_me) { rtLogDebug(__FUNCTION__); Locker locker(mIsolate); Isolate::Scope isolate_scope(mIsolate); HandleScope handle_scope(mIsolate); // Get parent Local context... Local<Context> local_context = clone_me->getLocalContext(); Context::Scope context_scope(local_context); // Create dummy sandbox for ContextifyContext::makeContext() ... Local<Object> sandbox = Object::New(mIsolate); // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - if( clone_me->has(SANDBOX_IDENTIFIER) ) { rtValue val_array = clone_me->get(SANDBOX_IDENTIFIER); rtObjectRef array = val_array.toObject(); int len = array.get<int>("length"); rtString s; for(int i = 0; i < len; i++) { array.get<rtString>( (uint32_t) i, s); // get 'name' for object rtValue obj = clone_me->get(s); // get object for 'name' if( obj.isEmpty() == false) { // Copy to var/module 'sandbox' under construction... Local<Value> module = local_context->Global()->Get( String::NewFromUtf8(mIsolate, s.cString() ) ); sandbox->Set( String::NewFromUtf8(mIsolate, s.cString()), module); } else { rtLogError("## FATAL: '%s' is empty !! - UNEXPECTED", s.cString()); } } } else { rtLogWarn("## WARNING: '%s' is undefined !! - UNEXPECTED", SANDBOX_IDENTIFIER); } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // // Clone a new context. { Local<Context> clone_local = node::makeContext(mIsolate, sandbox); // contextify context with 'sandbox' clone_local->SetEmbedderData(HandleMap::kContextIdIndex, Integer::New(mIsolate, mId)); #ifdef ENABLE_NODE_V_6_9 Local<Context> envCtx = Environment::GetCurrent(mIsolate)->context(); Local<String> symbol_name = FIXED_ONE_BYTE_STRING(mIsolate, "_contextifyPrivate"); Local<Private> private_symbol_name = Private::ForApi(mIsolate, symbol_name); MaybeLocal<Value> maybe_value = sandbox->GetPrivate(envCtx,private_symbol_name); Local<Value> decorated; if (true == maybe_value.ToLocal(&decorated)) { mContextifyContext = decorated.As<External>()->Value(); } #else Local<String> hidden_name = FIXED_ONE_BYTE_STRING(mIsolate, "_contextifyHidden"); mContextifyContext = sandbox->GetHiddenValue(hidden_name).As<External>()->Value(); #endif mContextId = GetContextId(clone_local); mContext.Reset(mIsolate, clone_local); // local to persistent // commenting below code as templates are isolcate specific /* Context::Scope context_scope(clone_local); Handle<Object> clone_global = clone_local->Global(); // Register wrappers in this cloned context... rtObjectWrapper::exportPrototype(mIsolate, clone_global); rtFunctionWrapper::exportPrototype(mIsolate, clone_global); mRtWrappers.Reset(mIsolate, clone_global); */ } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - }