void VJSNetServerClass::_pause (XBOX::VJSParms_callStaticFunction &ioParms, VJSNetServerObject *inServer)
{
	xbox_assert(inServer != NULL);

	sLONG	waitingTime;	// In milliseconds.

	if (!ioParms.CountParams())

		waitingTime = 1;

	else if (ioParms.CountParams() != 1 || !ioParms.IsNumberParam(1) || !ioParms.GetLongParam(1, &waitingTime)) {

		XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "1");
		return;

	}

	// Need support from VTCPConnectionListener.

	XBOX::vThrowError(XBOX::VE_JVSC_UNSUPPORTED_FUNCTION, "net.Server.pause()");
}
Example #2
0
void VJSMessagePort::PostMessageMethod (XBOX::VJSParms_callStaticFunction &ioParms, VJSMessagePort *inMessagePort)
{
    xbox_assert(inMessagePort != NULL);

    if (ioParms.CountParams() < 1) {

        XBOX::vThrowError(XBOX::VE_INVALID_PARAMETER);
        return;

    }

    VJSWorker			*worker		= VJSWorker::RetainWorker(ioParms.GetContext());
    XBOX::VJSValue		value		= ioParms.GetParamValue(1);
    VJSStructuredClone	*message	= VJSStructuredClone::RetainClone(value);

    inMessagePort->PostMessage(inMessagePort->GetOther(worker), message);
    XBOX::ReleaseRefCountable<VJSStructuredClone>(&message);
    XBOX::ReleaseRefCountable<VJSWorker>(&worker);
}
void VJSLanguageSyntaxTester::_GetSyntaxColoring( XBOX::VJSParms_callStaticFunction &ioParams, void * )
{
	// We expect two parameters -- the extension for the type of information we have (js, html, etc) and
	// a line of text to be colored.  We will perform the coloring, and return back to the user a list
	// of objects that contain the style information.
	if (ioParams.CountParams() < 2)	return;

	VString extension, data;
	if (!ioParams.GetStringParam( 1, extension ))	return;
	if (!ioParams.GetStringParam( 2, data ))		return;

	CLanguageSyntaxComponent *languageSyntax = (CLanguageSyntaxComponent *)VComponentManager::RetainComponent( (CType)CLanguageSyntaxComponent::Component_Type );
	if (!languageSyntax)	return;
	ISyntaxInterface *syntaxEngine = languageSyntax->GetSyntaxByExtension( extension );
	if (syntaxEngine) {
		// Now that we've got the syntax engine, we can ask it for the coloring information
		std::vector< size_t > offsets;
		std::vector< size_t > lengths;
		std::vector< sLONG > styles;
		syntaxEngine->GetColoringForTesting( data, offsets, lengths, styles );

		// Loop over the returned results, turning them into a vector of VJSValue objects
		std::vector< VJSValue > results;
		std::vector< JSColorResult * > releaseList;
		for (size_t i = 0; i < offsets.size(); i++) {
			JSColorResult *result = new JSColorResult( offsets[ i ], lengths[ i ], styles[ i ] );
			releaseList.push_back( result );
			results.push_back( VJSLanguageSyntaxTesterColorResults::CreateInstance( ioParams.GetContextRef(), result ) );
		}

		// Return an array of our results
		VJSArray arr( ioParams.GetContextRef() );
		arr.PushValues( results );
		ioParams.ReturnValue( arr );

		for (std::vector< JSColorResult * >::iterator iter = releaseList.begin(); iter != releaseList.end(); ++iter) {
			(*iter)->Release();
		}
	}

	languageSyntax->Release();
}
void VJSLanguageSyntaxTester::_Tokenize( XBOX::VJSParms_callStaticFunction &ioParams, void * )
{
	// We are expecting 2 JavaScript parameters:
	// - source code to tokenize
	// - extension of the fake file

	VString sourceCode, extension;

	if (ioParams.CountParams() == 2)
	{
		if (!ioParams.GetStringParam( 1, sourceCode ))	return;
		if (!ioParams.GetStringParam( 2, extension ))	return;
	}
	else
		return;

	CLanguageSyntaxComponent *languageSyntax = (CLanguageSyntaxComponent *)VComponentManager::RetainComponent( (CType)CLanguageSyntaxComponent::Component_Type );
	if (languageSyntax)
	{
		ISyntaxInterface *syntaxEngine = languageSyntax->GetSyntaxByExtension( extension );

		if (syntaxEngine)
		{
			VectorOfVString	tokens;

			syntaxEngine->GetTokensForTesting(sourceCode, tokens);

			VJSArray result( ioParams.GetContextRef() );
			VJSValue jsval(ioParams.GetContextRef());

			for (VectorOfVString::const_iterator it = tokens.begin(); it != tokens.end(); ++it)
			{
				jsval.SetString(*it);
				result.PushValue(jsval);
			}
			ioParams.ReturnValue(result);
 		}
		languageSyntax->Release();
	}
}
void VJSImage::_setPath(XBOX::VJSParms_callStaticFunction& ioParms, VJSPictureContainer* inPict)
{
	VPicture* pic = inPict->GetPict();
	VString path;
	if (pic != nil)
	{
		if (ioParms.CountParams() == 0 ||  ioParms.IsNullParam(1))
		{
			pic->SetOutsidePath(""); // empty string means no outside
		}
		else if (ioParms.IsBooleanParam(1))
		{
			pic->SetOutsidePath("*");
		}
		else if (ioParms.IsStringParam(1))
		{
			ioParms.GetStringParam(1, path);
			pic->SetOutsidePath(path);
			if (!path.IsEmpty())
				pic->ReloadFromOutsidePath();
		}
		else
		{
			VFile* file = ioParms.RetainFileParam(1);
			if (file != nil)
			{
				file->GetPath(path, FPS_POSIX);
				pic->SetOutsidePath(path);
				if (file->Exists())
					pic->ReloadFromOutsidePath();
			}
			else
				pic->SetOutsidePath("");
			QuickReleaseRefCountable(file);
		}
		//inPict->SetModif();
	}
}
void VJSNetServerSyncClass::_accept (XBOX::VJSParms_callStaticFunction &ioParms, VJSNetServerObject *inServer)
{
	xbox_assert(inServer != NULL);

	sLONG	timeOut;

	if (ioParms.CountParams() >= 1) {

		if (!ioParms.IsNumberParam(1) || !ioParms.GetLongParam(1, &timeOut)) {

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "1");
			return;

		}

		if (timeOut < 0) {

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "1");
			return;

		}

	} else

		timeOut = 0;

	XBOX::XTCPSock	*socket;

	// If socket returned is NULL, accept() has timed out or an error has occured.
	// An exception is thrown by GetNewConnectedSocket() if erroneous.

	if ((socket = inServer->fSockListener->GetNewConnectedSocket(timeOut)) == NULL) 

		ioParms.ReturnNullValue();

	else {

		XBOX::VTCPEndPoint	*endPoint		= NULL;
		VJSNetSocketObject	*socketObject	= NULL;
	
		if ((endPoint = new XBOX::VTCPEndPoint(socket)) == NULL 
		|| (socketObject = new VJSNetSocketObject(true, VJSNetSocketObject::eTYPE_TCP4, false)) == NULL) {

			if (endPoint != NULL)

				endPoint->Release();

			if (socketObject != NULL)

				socketObject->Release();

			socket->Close();
			delete socket;

			XBOX::vThrowError(XBOX::VE_MEMORY_FULL);
		
		} else {

			socketObject->fEndPoint = endPoint;
			socketObject->fEndPoint->SetNoDelay(false);

			XBOX::VJSObject	newSocketSync = VJSNetSocketSyncClass::CreateInstance(ioParms.GetContext(), socketObject);
			XBOX::VString	address;

			socketObject->fObjectRef = newSocketSync.GetObjectRef();
			socketObject->fWorker = VJSWorker::RetainWorker(ioParms.GetContext());

			socketObject->fEndPoint->GetIP(address);
			newSocketSync.SetProperty("remoteAddress", address);
			newSocketSync.SetProperty("remotePort", (sLONG) socketObject->fEndPoint->GetPort() & 0xffff);

			ioParms.ReturnValue(newSocketSync);

		}

	}
}
void VJSNetServerSyncClass::_listen (XBOX::VJSParms_callStaticFunction &ioParms, VJSNetServerObject *inServer)
{
	xbox_assert(inServer != NULL);

	sLONG	port;

	if (ioParms.CountParams() >= 1) {

		if (!ioParms.IsNumberParam(1) || !ioParms.GetLongParam(1, &port)) {

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "1");
			return;

		}

	} else

		port = 0;		// Will use a random port (useful?).

// Re-use code of async listen().

#if WITH_DEPRECATED_IPV4_API
	
	uLONG	address;

	if (ioParms.CountParams() >= 2) {

		XBOX::VString	hostname;

		if (!ioParms.IsStringParam(2) || !ioParms.GetStringParam(2, hostname)) {

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_STRING, "2");
			return;

		}

		address = XBOX::ServerNetTools::ResolveAddress(hostname);

	} else

		address = 0;	// Same as "localhost".

#else

	//jmo - je ne comprends pas bien la logique du resolve sur le hostname...
	//      On veut une IP 'publique' ? J'ai simplifié.
	
	VString address=VNetAddress::GetAnyIP();

#endif
	
	// We are already listening, stop previous listener.

	if (inServer->fConnectionListener != NULL)

		inServer->Close();

	// Setup new listener.

	if ((inServer->fSockListener = new XBOX::VSockListener()) == NULL) {

		XBOX::vThrowError(XBOX::VE_MEMORY_FULL);
		return;

	}

	XBOX::VError	error;

	error = XBOX::VE_OK;
	if (inServer->fIsSSL)
		
		error = inServer->fSockListener->SetKeyAndCertificate(inServer->fKey, inServer->fCertificate);

	if (error != XBOX::VE_OK) {

		inServer->Close();
		XBOX::vThrowError(error);

	}
	else if (!inServer->fSockListener->SetBlocking(true)
	|| !inServer->fSockListener->AddListeningPort(address, port, inServer->fIsSSL)	
	|| !inServer->fSockListener->StartListening()) {

		inServer->Close();
		XBOX::vThrowError(XBOX::VE_SRVR_FAILED_TO_CREATE_LISTENING_SOCKET);
		
	}
	else {

		inServer->fAddress = address;	
		inServer->fPort = port;	

	}
}
void VJSNetServerClass::_listen (XBOX::VJSParms_callStaticFunction &ioParms, VJSNetServerObject *inServer)
{
	xbox_assert(inServer != NULL);

	XBOX::VString	address;
	sLONG			port;

	if (!ioParms.CountParams()) {

		XBOX::vThrowError(XBOX::VE_JVSC_EXPECTING_PARAMETER, "net.Server.listen()");
		return;

	}

	if (!ioParms.IsNumberParam(1) || !ioParms.GetLongParam(1, &port)) {
		
		XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_NUMBER, "1");
		return;

	}

	XBOX::VString	hostname;
	XBOX::VJSObject	callback(ioParms.GetContext());
	bool			hasCallback;

	hostname = "";
	hasCallback = false;
	if (ioParms.CountParams() >= 2) {

		if (ioParms.IsStringParam(2)) {
			
			if (!ioParms.GetStringParam(2, hostname)) {

				XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_STRING, "2");
				return;

			}

		} else if (ioParms.IsObjectParam(2) && ioParms.GetParamFunc(2, callback)) {

			hasCallback = true;

		} else {

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_FUNCTION, "2");
			return;

		}

	} 

	if (ioParms.CountParams() == 3 ) {
	
		if ((hasCallback || !ioParms.IsObjectParam(3) || !ioParms.GetParamFunc(3, callback))) {

			XBOX::vThrowError(XBOX::VE_JVSC_WRONG_PARAMETER_TYPE_FUNCTION, "3");
			return;

		} else

			hasCallback = true;

	}

	// We are already listening, stop previous listener.

	if (inServer->fConnectionListener != NULL)

		inServer->Close();

	// Set up listener.
	
	if ((inServer->fConnectionListener = new XBOX::VTCPConnectionListener())== NULL) {

		XBOX::vThrowError(XBOX::VE_MEMORY_FULL);
		return;

	} 

	if (inServer->fIsSSL)

		inServer->fConnectionListener->SetSSLKeyAndCertificate(inServer->fCertificate, inServer->fKey);

	VJSNetSocketObject::sMutex.Lock();

	if (VJSNetSocketObject::sSelectIOPool == NULL)

		VJSNetSocketObject::sSelectIOPool = new XBOX::VTCPSelectIOPool();

	VJSNetSocketObject::sMutex.Unlock();

	inServer->fConnectionListener->AddSelectIOPool(VJSNetSocketObject::sSelectIOPool);

	VJSWorker	*worker;

	worker = VJSWorker::RetainWorker(ioParms.GetContext());

	VJSConnectionHandlerFactory	*connectionHandlerFactory;
	
	if ((connectionHandlerFactory = new VJSConnectionHandlerFactory(worker, inServer, inServer->fIsSSL)) == NULL) {

		XBOX::vThrowError(XBOX::VE_MEMORY_FULL);
		XBOX::ReleaseRefCountable<VJSWorker>(&worker);
		return;

	}

#if WITH_DEPRECATED_IPV4_API
	
	sLONG	resolvedAddress;

	if (hostname.GetLength()) {

		address = hostname;
		resolvedAddress = XBOX::ServerNetTools::ResolveAddress(hostname);

	} else {

		address = "0.0.0.0";

		std::vector<IP4>	localIPs;

		if (XBOX::ServerNetTools::GetLocalIPv4Addresses(localIPs))

			resolvedAddress = localIPs[0];

		else

			resolvedAddress = 0;	// Should be same as above.

	}

	connectionHandlerFactory->SetIP(resolvedAddress);

#else

	XBOX::VNetAddressList	addrList;
	bool				isIPv6;

	if (hostname.GetLength()) {

		XBOX::VNetAddress	addr(hostname, port);

		isIPv6 = addr.IsV6();
		addrList.FromDnsQuery(hostname, port);
		
	} else {

		addrList.FromLocalInterfaces();
		isIPv6 = false;

	}

	// Always take first matching type address.

	XBOX::VNetAddressList::const_iterator	it;

	for (it = addrList.begin(); it != addrList.end(); it++)

		if ((*it).IsV6() == isIPv6)

			break;

	address = (*it).GetIP();
		
	connectionHandlerFactory->SetIP(address);

#endif	

	connectionHandlerFactory->AddNewPort(port);

	XBOX::VError	error;

	error = inServer->fConnectionListener->AddConnectionHandlerFactory(connectionHandlerFactory);
	connectionHandlerFactory->Release();	// AddConnectionHandlerFactory() has done a retain().

	if (error != XBOX::VE_OK 
	|| (error = inServer->fConnectionListener->StartListening()) != XBOX::VE_OK) 
		
		XBOX::vThrowError(error);

	else {

		inServer->fAddress = address;
		inServer->fPort = port;
			
		if (hasCallback) 
			
			inServer->AddListener("listening", callback, false);
		
		worker->QueueEvent(VJSNetEvent::Create(inServer, "listening"));

	}
	XBOX::ReleaseRefCountable<VJSWorker>(&worker);
}
void VJSLanguageSyntaxTester::_ParseFile( XBOX::VJSParms_callStaticFunction &ioParams, void * )
{
	// The caller has passed us the path to the symbol table and the path to the file to be
	// parsed.  We want to parse that file and then return back to the caller once the
	// parsing is complete.
	
	// We are expecting 4 parameters.  One for the path to the symbol table,
	// one for the path to the test file
	if (ioParams.CountParams() < 4)	return;

	VString symTablePathStr, testFilePathStr, testFileBaseFolderStr, testFileExecContextStr;

	if (!ioParams.GetStringParam( 1, symTablePathStr ))	return;
	if (!ioParams.GetStringParam( 2, testFilePathStr ))	return;
	if (!ioParams.GetStringParam( 3, testFileBaseFolderStr ))	return;
	if (!ioParams.GetStringParam( 4, testFileExecContextStr ))	return;

	VFilePath testFilePath( testFilePathStr, FPS_POSIX);
	
	if ( ! testFilePath.IsValid() )
		return;

	ESymbolFileBaseFolder	baseFolder;
	ESymbolFileExecContext	execContext;

	// Get file base folder
	if (testFileBaseFolderStr == CVSTR("project"))
		baseFolder = eSymbolFileBaseFolderProject;
	else if (testFileBaseFolderStr == CVSTR("jsf"))
		baseFolder = eSymbolFileBaseFolderStudio;
	else
		return;

	// Get file execution context
	if (testFileExecContextStr == CVSTR("client"))
		execContext = eSymbolFileExecContextClient;
	else if (testFileExecContextStr == CVSTR("server"))
		execContext = eSymbolFileExecContextServer;
	else if (testFileExecContextStr == CVSTR("both"))
		execContext = eSymbolFileExecContextClientServer;
	else
		return;

	VFilePath			symbolTablePath( symTablePathStr, FPS_POSIX);

	if ( ! symbolTablePath.IsValid() )
		return;
	
	CLanguageSyntaxComponent *languageSyntax = (CLanguageSyntaxComponent *)VComponentManager::RetainComponent( (CType)CLanguageSyntaxComponent::Component_Type );
	if (languageSyntax)
	{
		// First, load up the symbol table as an actual table instead of just a path string
		ISymbolTable *symTable = languageSyntax->CreateSymbolTable();
		if (symTable)
		{
			VFile file(symbolTablePath);

			if (symTable->OpenSymbolDatabase( file))
			{
				IDocumentParserManager *parserManager = languageSyntax->CreateDocumentParserManager();
				// Limit parser waiter scope as destructor will disconnect parsing signal
				{
					ParsingWaiter	waiter( parserManager);
					VString			extension;

					testFilePath.GetExtension(extension);
					if ( extension == CVSTR("waModel") )
					{
						VLanguageSyntaxTesterCatalog* catalog = new VLanguageSyntaxTesterCatalog( testFilePath );

						parserManager->ScheduleTask( (const void *)0xFEEDFACE, catalog, waiter.GetCookie(), symTable, IDocumentParserManager::kPriorityAboveNormal);
						catalog->Release();
					}
					else
					{
						VSymbolFileInfos	fileInfos(testFilePath, baseFolder, execContext);

						parserManager->ScheduleTask( (const void *)0xFEEDFACE, /* Just needs to be unique per scheduler, but since this is a static method, there is no this pointer*/
													 fileInfos, waiter.GetCookie(), symTable, IDocumentParserManager::kPriorityAboveNormal );
					}
					waiter.Wait();
				}
				parserManager->Release();
			}
			symTable->Release();
		}
		languageSyntax->Release();
	}
}
void VJSLanguageSyntaxTester::_GotoDefinition( XBOX::VJSParms_callStaticFunction &ioParams, void * )
{
	VString filePathStr, symTablePathStr, selectionStr;
	sLONG	line = 0;

	if (ioParams.CountParams() == 4)
	{
		if (!ioParams.GetStringParam( 1, symTablePathStr )) return;
		if (!ioParams.GetStringParam( 2, filePathStr ))		return;
		if (!ioParams.GetLongParam( 3, &line ))				return;
		if (!ioParams.GetStringParam( 4, selectionStr ))	return;
	}
	else
		return;

	VFilePath symbolTablePath( symTablePathStr, FPS_POSIX);
	VFilePath filePath( filePathStr, FPS_POSIX);

	if ( ! symbolTablePath.IsValid() || ! filePath.IsValid() )
		return;

	if ( line < 1 )
		return;

	CLanguageSyntaxComponent *languageSyntax = (CLanguageSyntaxComponent *)VComponentManager::RetainComponent( (CType)CLanguageSyntaxComponent::Component_Type );
	if (languageSyntax)
	{
		// First, load up the symbol table as an actual table instead of just a path string
		ISymbolTable *symTable = NULL;
		if (!symTablePathStr.IsEmpty())
		{
			symTable = languageSyntax->CreateSymbolTable();
			if (symTable)
			{
				VFile file(symbolTablePath);

				if (symTable->OpenSymbolDatabase( file ))
				{
					// Now that we have all of the parameters grabbed, we can figure out which language syntax engine
					// we want to load up (based on the test file), and ask it to give us completions.  We can then take
					// those completions and turn them into an array of values to pass back to the caller.
					VString extension;
					filePath.GetExtension( extension );
					ISyntaxInterface *syntaxEngine = languageSyntax->GetSyntaxByExtension( extension );
					if (syntaxEngine)
					{
						// Now that we've got the syntax engine, we can ask it for the completions we need
						std::vector< IDefinition > definitions;
						syntaxEngine->GetDefinitionsForTesting( selectionStr, symTable, filePath.GetPath(), line, definitions );

						JSDefinitionResult *results = new JSDefinitionResult( definitions );
						ioParams.ReturnValue( VJSLanguageSyntaxTesterDefinitionResults::CreateInstance( ioParams.GetContextRef(), results ) );
						results->Release();
					}
				}
				symTable->Release();
			}
		}
		languageSyntax->Release();
	}
}
void VJSLanguageSyntaxTester::_GetSymbol( XBOX::VJSParms_callStaticFunction &ioParams, void * )
{
	// We are expecting 4 JavaScript parameters:
	// - path to the symbol table
	// - symbol name
	// - symbol definition file
	// - symbol definition line number
	
	VString	symTablePathStr, symbolName, symbolDefPath;
	sLONG	symbolDefLineNumber;

	if (ioParams.CountParams() == 4) {
		if (!ioParams.GetStringParam( 1, symTablePathStr )) return;
		if (!ioParams.GetStringParam( 2, symbolName ))		return;
		if (!ioParams.GetStringParam( 3, symbolDefPath )) return;
		if (!ioParams.GetLongParam( 4, &symbolDefLineNumber ))		return;
	}
	else
		return;
	
	VFilePath symbolTablePath( symTablePathStr, FPS_POSIX);
	VFilePath symbolDefFilePath( symbolDefPath, FPS_POSIX);

	if ( ! symbolTablePath.IsValid() || ! symbolDefFilePath.IsValid() )
		return;

	CLanguageSyntaxComponent *languageSyntax = (CLanguageSyntaxComponent *)VComponentManager::RetainComponent( (CType)CLanguageSyntaxComponent::Component_Type );
	if (languageSyntax)
	{
		// First, load up the symbol table as an actual table instead of just a path string
		ISymbolTable *symTable = NULL;
		if (!symTablePathStr.IsEmpty())
		{
			symTable = languageSyntax->CreateSymbolTable();
			if (symTable)
			{
				VFile file(symbolTablePath);

				if (symTable->OpenSymbolDatabase( file ))
				{
					// Get symbol file
					std::vector< Symbols::IFile * > files = symTable->GetFilesByPathAndBaseFolder( symbolDefFilePath, eSymbolFileBaseFolderProject );	
					if ( ! files.empty() )
					{
						Symbols::IFile *file = files.front();
						file->Retain();
						for (std::vector< Symbols::IFile * >::iterator iter = files.begin(); iter != files.end(); ++iter)
							(*iter)->Release();

						// Gets symbol corresponding to given parameters
						Symbols::ISymbol* owner = symTable->GetSymbolOwnerByLine(file, symbolDefLineNumber);
						Symbols::ISymbol* sym = NULL;

						if (NULL != owner && owner->GetName() == symbolName)
						{
							sym = owner;
							sym->Retain();
						}
						
						if (NULL == sym)
						{
							std::vector< Symbols::ISymbol * >	syms = symTable->GetSymbolsByName(owner, symbolName,file);
							for (std::vector< Symbols::ISymbol * >::iterator iter = syms.begin(); iter != syms.end(); ++iter)
							{
								if ( ( (*iter)->GetLineNumber() + 1 ) == symbolDefLineNumber )
								{
									sym = *iter;
									(*iter)->Retain();
								}
								(*iter)->Release();
							}	
						}

						if (NULL != sym)
						{
							VJSObject	result(ioParams.GetContextRef());
							VJSValue	jsval(ioParams.GetContextRef());
							VString		signature;

							symTable->GetSymbolSignature( sym, signature );

							result.MakeEmpty();

							jsval.SetString( sym->GetName() );
							result.SetProperty(L"name", jsval, JS4D::PropertyAttributeNone);

							jsval.SetString( sym->GetTypeName() );
							result.SetProperty(L"type", jsval, JS4D::PropertyAttributeNone);

							jsval.SetNumber( sym->GetLineNumber() + 1 );
							result.SetProperty(L"line", jsval, JS4D::PropertyAttributeNone);

							jsval.SetString( signature );
							result.SetProperty(L"signature", jsval, JS4D::PropertyAttributeNone);

							jsval.SetString( sym->GetKindString() );
							result.SetProperty(L"kind", jsval, JS4D::PropertyAttributeNone);

							ioParams.ReturnValue(result);
							sym->Release();
						}
						
						if (NULL != owner)
							owner->Release();
						file->Release();	
					}
				}
				symTable->Release();
			}
		}
		languageSyntax->Release();
	}
}
void VJSLanguageSyntaxTester::_GetCompletions( XBOX::VJSParms_callStaticFunction &ioParams, void * )
{
	// We are expecting 5 parameters for JavaScript.  One for the path to the symbol table, one for the path to the test file (which
	// must already be a part of the symbol table), one for the line number within the file, one for the string that
	// we are going to be completing at that point and one for the completion mode.  If we get only three parameters, then it's a CSS completion test, which is
	// fine -- we just modify the parameters we pass into GetSuggestionsForTesting.
	
	VString symTablePathStr, testFilePathStr, completionString, completionModeStr;
	sLONG completionLocation;
	if (ioParams.CountParams() == 5) {
		if (!ioParams.GetStringParam( 1, symTablePathStr ))		return;
		if (!ioParams.GetStringParam( 2, completionString ))	return;
		if (!ioParams.GetStringParam( 3, testFilePathStr ))		return;
		if (!ioParams.GetLongParam( 4, &completionLocation ))	return;
		if (!ioParams.GetStringParam( 5, completionModeStr ))	return;
	} else if (ioParams.CountParams() == 3) {
		bool curlyBraces;
		if (!ioParams.GetStringParam( 1, completionString ))	return;
		if (!ioParams.GetBoolParam( 2, &curlyBraces ))			return;
		if (!ioParams.GetStringParam( 3, testFilePathStr ))		return;

		// We fudge the completion location information when working with CSS files so that it
		// denotes whether we're inside of curly braces or not.
		completionLocation = curlyBraces ? 1 : 0;
	} else {
		return;
	}
	
	VFilePath symbolTablePath( symTablePathStr, FPS_POSIX);
	VFilePath testFilePath( testFilePathStr, FPS_POSIX);

	if ( ! symbolTablePath.IsValid() || ! testFilePath.IsValid() )
		return;

	EJSCompletionTestingMode completionMode;
	if (completionModeStr == "text")
		completionMode = eText;
	else if (completionModeStr == "displayText")
		completionMode = eDisplayText;
	else
		return;

	CLanguageSyntaxComponent *languageSyntax = (CLanguageSyntaxComponent *)VComponentManager::RetainComponent( (CType)CLanguageSyntaxComponent::Component_Type );
	if (languageSyntax)
	{
		// First, load up the symbol table as an actual table instead of just a path string
		ISymbolTable *symTable = NULL;
		if (!symTablePathStr.IsEmpty())
		{
			symTable = languageSyntax->CreateSymbolTable();
			if ( symTable )
			{
				VFile file(symbolTablePath);
				if (symTable->OpenSymbolDatabase( file ))
				{
					// Now that we have all of the parameters grabbed, we can figure out which language syntax engine
					// we want to load up (based on the test file), and ask it to give us completions.  We can then take
					// those completions and turn them into an array of values to pass back to the caller.
					VString extension;
					testFilePath.GetExtension( extension );
					ISyntaxInterface *syntaxEngine = languageSyntax->GetSyntaxByExtension( extension );
					if (syntaxEngine)
					{
						// Now that we've got the syntax engine, we can ask it for the completions we need
						std::vector< VString > suggestions;
						syntaxEngine->GetSuggestionsForTesting( completionString, symTable, testFilePath.GetPath() , completionLocation, completionMode, suggestions );

						JSResult *results = new JSResult( suggestions );
						ioParams.ReturnValue( VJSLanguageSyntaxTesterResults::CreateInstance( ioParams.GetContextRef(), results ) );
						results->Release();
					}
				}
				symTable->Release();
			}
		}
		languageSyntax->Release();
	}
}