Changeset View
Changeset View
Standalone View
Standalone View
source/scriptinterface/ScriptInterface.cpp
Show First 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | struct ScriptInterface_impl | ||||
void Register(const char* name, JSNative fptr, uint nargs) const; | void Register(const char* name, JSNative fptr, uint nargs) const; | ||||
// Take care to keep this declaration before heap rooted members. Destructors of heap rooted | // Take care to keep this declaration before heap rooted members. Destructors of heap rooted | ||||
// members have to be called before the runtime destructor. | // members have to be called before the runtime destructor. | ||||
shared_ptr<ScriptRuntime> m_runtime; | shared_ptr<ScriptRuntime> m_runtime; | ||||
JSContext* m_cx; | JSContext* m_cx; | ||||
JS::PersistentRootedObject m_glob; // global scope object | JS::PersistentRootedObject m_glob; // global scope object | ||||
JSCompartment* m_comp; | JSCompartment* m_formerCompartment; | ||||
boost::rand48* m_rng; | boost::rand48* m_rng; | ||||
JS::PersistentRootedObject m_nativeScope; // native function scope object | JS::PersistentRootedObject m_nativeScope; // native function scope object | ||||
}; | }; | ||||
namespace | namespace | ||||
{ | { | ||||
JSClass global_class = { | JSClass global_class = { | ||||
▲ Show 20 Lines • Show All 252 Lines • ▼ Show 20 Lines | if (m->m_rng == NULL) | ||||
return false; | return false; | ||||
nbr = generate_uniform_real(*(m->m_rng), 0.0, 1.0); | nbr = generate_uniform_real(*(m->m_rng), 0.0, 1.0); | ||||
return true; | return true; | ||||
} | } | ||||
ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) : | ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) : | ||||
m_runtime(runtime), m_glob(runtime->m_rt), m_nativeScope(runtime->m_rt) | m_runtime(runtime), m_glob(runtime->m_rt), m_nativeScope(runtime->m_rt) | ||||
{ | { | ||||
bool ok; | |||||
m_cx = JS_NewContext(m_runtime->m_rt, STACK_CHUNK_SIZE); | m_cx = JS_NewContext(m_runtime->m_rt, STACK_CHUNK_SIZE); | ||||
ENSURE(m_cx); | ENSURE(m_cx); | ||||
JS_SetOffthreadIonCompilationEnabled(m_runtime->m_rt, true); | JS_SetOffthreadIonCompilationEnabled(m_runtime->m_rt, true); | ||||
// For GC debugging: | // For GC debugging: | ||||
// JS_SetGCZeal(m_cx, 2, JS_DEFAULT_ZEAL_FREQ); | // JS_SetGCZeal(m_cx, 2, JS_DEFAULT_ZEAL_FREQ); | ||||
Show All 11 Lines | ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) : | ||||
JS::CompartmentOptions opt; | JS::CompartmentOptions opt; | ||||
opt.setVersion(JSVERSION_LATEST); | opt.setVersion(JSVERSION_LATEST); | ||||
// Keep JIT code during non-shrinking GCs. This brings a quite big performance improvement. | // Keep JIT code during non-shrinking GCs. This brings a quite big performance improvement. | ||||
opt.setPreserveJitCode(true); | opt.setPreserveJitCode(true); | ||||
JSAutoRequest rq(m_cx); | JSAutoRequest rq(m_cx); | ||||
JS::RootedObject globalRootedVal(m_cx, JS_NewGlobalObject(m_cx, &global_class, NULL, JS::OnNewGlobalHookOption::FireOnNewGlobalHook, opt)); | JS::RootedObject globalRootedVal(m_cx, JS_NewGlobalObject(m_cx, &global_class, NULL, JS::OnNewGlobalHookOption::FireOnNewGlobalHook, opt)); | ||||
m_comp = JS_EnterCompartment(m_cx, globalRootedVal); | m_formerCompartment = JS_EnterCompartment(m_cx, globalRootedVal); | ||||
ok = JS_InitStandardClasses(m_cx, globalRootedVal); | ENSURE(JS_InitStandardClasses(m_cx, globalRootedVal)); | ||||
ENSURE(ok); | |||||
m_glob = globalRootedVal.get(); | m_glob = globalRootedVal.get(); | ||||
JS_DefineProperty(m_cx, m_glob, "global", globalRootedVal, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); | JS_DefineProperty(m_cx, m_glob, "global", globalRootedVal, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); | ||||
m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, nullptr, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); | m_nativeScope = JS_DefineObject(m_cx, m_glob, nativeScopeName, nullptr, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); | ||||
JS_DefineFunction(m_cx, globalRootedVal, "print", ::print, 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); | JS_DefineFunction(m_cx, globalRootedVal, "print", ::print, 0, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); | ||||
JS_DefineFunction(m_cx, globalRootedVal, "log", ::logmsg, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); | JS_DefineFunction(m_cx, globalRootedVal, "log", ::logmsg, 1, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT); | ||||
Show All 9 Lines | ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptRuntime>& runtime) : | ||||
runtime->RegisterContext(m_cx); | runtime->RegisterContext(m_cx); | ||||
} | } | ||||
ScriptInterface_impl::~ScriptInterface_impl() | ScriptInterface_impl::~ScriptInterface_impl() | ||||
{ | { | ||||
m_runtime->UnRegisterContext(m_cx); | m_runtime->UnRegisterContext(m_cx); | ||||
{ | { | ||||
JSAutoRequest rq(m_cx); | JSAutoRequest rq(m_cx); | ||||
JS_LeaveCompartment(m_cx, m_comp); | JS_LeaveCompartment(m_cx, m_formerCompartment); | ||||
} | } | ||||
JS_DestroyContext(m_cx); | JS_DestroyContext(m_cx); | ||||
} | } | ||||
void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint nargs) const | void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint nargs) const | ||||
{ | { | ||||
JSAutoRequest rq(m_cx); | JSAutoRequest rq(m_cx); | ||||
JS::RootedObject nativeScope(m_cx, m_nativeScope); | JS::RootedObject nativeScope(m_cx, m_nativeScope); | ||||
▲ Show 20 Lines • Show All 156 Lines • ▼ Show 20 Lines | if (!JS_ValueToObject(m->m_cx, val, &obj) || !obj) | ||||
return false; | return false; | ||||
// Check that the named function actually exists, to avoid ugly JS error reports | // Check that the named function actually exists, to avoid ugly JS error reports | ||||
// when calling an undefined value | // when calling an undefined value | ||||
bool found; | bool found; | ||||
if (!JS_HasProperty(m->m_cx, obj, name, &found) || !found) | if (!JS_HasProperty(m->m_cx, obj, name, &found) || !found) | ||||
return false; | return false; | ||||
bool ok = JS_CallFunctionName(m->m_cx, obj, name, argv, ret); | return JS_CallFunctionName(m->m_cx, obj, name, argv, ret); | ||||
return ok; | |||||
} | } | ||||
bool ScriptInterface::CreateObject_(JSContext* cx, JS::MutableHandleObject object) | bool ScriptInterface::CreateObject_(JSContext* cx, JS::MutableHandleObject object) | ||||
{ | { | ||||
// JSAutoRequest is the responsibility of the caller | // JSAutoRequest is the responsibility of the caller | ||||
object.set(JS_NewPlainObject(cx)); | object.set(JS_NewPlainObject(cx)); | ||||
▲ Show 20 Lines • Show All 266 Lines • ▼ Show 20 Lines | bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& code) const | ||||
if (!JS::CompileFunction(m->m_cx, emptyScopeChain, options, NULL, 0, NULL, | if (!JS::CompileFunction(m->m_cx, emptyScopeChain, options, NULL, 0, NULL, | ||||
reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &func)) | reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &func)) | ||||
return false; | return false; | ||||
JS::RootedValue rval(m->m_cx); | JS::RootedValue rval(m->m_cx); | ||||
return JS_CallFunction(m->m_cx, nullptr, func, JS::HandleValueArray::empty(), &rval); | return JS_CallFunction(m->m_cx, nullptr, func, JS::HandleValueArray::empty(), &rval); | ||||
} | } | ||||
shared_ptr<ScriptRuntime> ScriptInterface::CreateRuntime(shared_ptr<ScriptRuntime> parentRuntime, int runtimeSize, int heapGrowthBytesGCTrigger) | |||||
{ | |||||
return shared_ptr<ScriptRuntime>(new ScriptRuntime(parentRuntime, runtimeSize, heapGrowthBytesGCTrigger)); | |||||
} | |||||
bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::wstring& code) const | bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::wstring& code) const | ||||
{ | { | ||||
JSAutoRequest rq(m->m_cx); | JSAutoRequest rq(m->m_cx); | ||||
utf16string codeUtf16(code.begin(), code.end()); | utf16string codeUtf16(code.begin(), code.end()); | ||||
uint lineNo = 1; | uint lineNo = 1; | ||||
// CompileOptions does not copy the contents of the filename string pointer. | // CompileOptions does not copy the contents of the filename string pointer. | ||||
// Passing a temporary string there will cause undefined behaviour, so we create a separate string to avoid the temporary. | // Passing a temporary string there will cause undefined behaviour, so we create a separate string to avoid the temporary. | ||||
std::string filenameStr = filename.string8(); | std::string filenameStr = filename.string8(); | ||||
▲ Show 20 Lines • Show All 258 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator