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);
}
void MetadataNode::SetPackageMetadata(Isolate *isolate, Local<Object> value, MetadataNode *node)
{
	value->SetHiddenValue(ConvertToV8String("tns::PackageMetadata"), External::New(isolate, node));
}
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 MetadataNode::SetInstanceMetadata(Isolate *isolate, Local<Object> value, MetadataNode *node)
{
	auto key = Local<String>::New(isolate, *s_metadataKey);
	value->SetHiddenValue(key, External::New(isolate, node));
}
Пример #5
0
   Handle<Object> WrapComponent(Handle<Object> wrappedes, ScriptSystem* scriptsys, dtEntity::EntityId eid, dtEntity::Component* v)
   {

      HandleScope handle_scope;

      Handle<Object> wrapped = scriptsys->GetFromComponentMap(v->GetType(), eid);
      if(!wrapped.IsEmpty())
      {
         return wrapped;
      }

      Handle<FunctionTemplate> templt = GetScriptSystem()->GetTemplateBySID(s_componentWrapper);
      if(templt.IsEmpty())
      {

         templt = FunctionTemplate::New();

         templt->SetClassName(String::New("Component"));
         templt->InstanceTemplate()->SetInternalFieldCount(1);

         Handle<ObjectTemplate> proto = templt->PrototypeTemplate();

         proto->Set("equals", FunctionTemplate::New(COEquals));
         proto->Set("getType", FunctionTemplate::New(COGetType));
         proto->Set("properties", FunctionTemplate::New(COProperties));
         proto->Set("toString", FunctionTemplate::New(COToString));
         proto->Set("finished", FunctionTemplate::New(COFinished));
         proto->Set("copyPropertyValues", FunctionTemplate::New(COCopyPropertyValues));

         GetScriptSystem()->SetTemplateBySID(s_componentWrapper, templt);
      }


      Local<Object> instance = templt->GetFunction()->NewInstance();
      instance->SetInternalField(0, External::New(v));
      instance->SetHiddenValue(scriptsys->GetEntityIdString(), Uint32::New(eid));

      // GetStringFromSID and conversion to v8::String is costly, create a 
      // hidden value in entity system wrapper that stores
      // strings and their string ids as name=>value pairs
      Handle<Value> propnamesval = wrappedes->GetHiddenValue(scriptsys->GetPropertyNamesString());
      if(propnamesval.IsEmpty())
      {
         Handle<Object> names = Object::New();
         dtEntity::PropertyGroup::const_iterator i;
         const dtEntity::PropertyGroup& props = v->Get();
         for(i = props.begin(); i != props.end(); ++i)
         {
            dtEntity::StringId sid = i->first;
            std::string propname = dtEntity::GetStringFromSID(sid);
            names->Set(String::New(propname.c_str()), WrapSID(sid));
         }
         wrappedes->SetHiddenValue(scriptsys->GetPropertyNamesString(), names);
         propnamesval = names;
      }

      Handle<Object> propnames = Handle<Object>::Cast(propnamesval);
      Handle<Array> keys = propnames->GetPropertyNames();
      for(unsigned int i = 0; i < keys->Length(); ++i)
      {
         Handle<String> str = keys->Get(i)->ToString();
         dtEntity::StringId sid = UnwrapSID(propnames->Get(str));
         dtEntity::Property* prop = v->Get(sid);
         if(prop == NULL)
         {
            LOG_ERROR("Could not find property in component: " << ToStdString(str));
            continue;
         }
         Handle<External> ext = v8::External::New(static_cast<void*>(prop));
         instance->SetAccessor(str, COPropertyGetter, COPropertySetter, ext);
      }
      
      // store wrapped component to script system
      scriptsys->AddToComponentMap(v->GetType(), eid, instance);
      return handle_scope.Close(instance);
   }