#include "jsc.h"

JavaScript::JavaScript():lock(SilenceAssertionsOnly){
	JSC::initializeThreading();
	globalData = JSGlobalData::create(ThreadStackTypeLarge).releaseRef();
	jsglobalObject = new(globalData) JSGlobalObject;
}

JavaScript::~JavaScript(){
	globalData->heap.destroy();
	globalData->deref();
}

void JavaScript::AddNativeFunction(const char* name,NativeFunction function){
	jsglobalObject->putDirectFunction(
		jsglobalObject->globalExec(),
		new(jsglobalObject->globalExec()) NativeFunctionWrapper(
				jsglobalObject->globalExec(),
				jsglobalObject, 
				jsglobalObject->prototypeFunctionStructure(),
				1,
				Identifier(jsglobalObject->globalExec(), name),
				function
			)
	);
}

bool JavaScript::Execute(const Upp::String& code,Upp::String& result){
	bool succes;
	Completion completion = evaluate(jsglobalObject->globalExec(),jsglobalObject->globalScopeChain(), makeSource(UString(code)));
	if (completion.complType() == Throw){
		result = completion.value().toString(jsglobalObject->globalExec()).UTF8String().data();
		succes = false;
	} else {
		result = completion.value().toString(jsglobalObject->globalExec()).UTF8String().data();
		succes = true;
	}
	jsglobalObject->globalExec()->clearException();
	return succes;
}

bool JavaScript::ExecuteFile(const Upp::String& filename,Upp::String& result){
	if(!FileExists(filename)){
		result = "File "+filename+" not found!";
		return false;
	} else {
		return Execute(LoadFile(filename),result);
	}
}

bool JavaScript::CheckSyntax(const Upp::String& code,Upp::String& result){
	JSGlobalObject* global = jsglobalObject->globalExec()->lexicalGlobalObject();
	Completion completition = checkSyntax(global->globalExec(),makeSource(UString(code),"interpreter"));
	if (completition.complType() == Throw){
		result = completition.value().toString(global->globalExec()).UTF8String().data();
		return false;
	} else {
		result = "OK";
		return true;
	}
}
