[SM68 2/2] Update to Spidermonkey 68 APIs

No noteworthy API changes.

Details:
- Remove UTF16 script execution since UTF8 is supported in SM68 and
going forward
- Several new headers includes are required
- Realms replace Compartments as "global holders" (see meta-Bug 1357862)
- JSRequests are removed entirely (Bug 722345), see also aae417bd29
- Trivial API updates in ProxyHandlers, ArrayBuffer, Warnings, GC
reasons, Context options, ObjectIsFunction, ValueVectors and
JSCompartment

See also the migration guide:
https://github.com/mozilla-spidermonkey/spidermonkey-embedding-examples/blob/esr78/docs/Migration%20Guide.md

Tested by: Freagarach, Stan, Subitaneo
Fixes #5860

Differential Revision: https://code.wildfiregames.com/D3144
This was SVN commit r24297.
This commit is contained in:
wraitii
2020-11-30 09:03:20 +00:00
parent d8332a2938
commit 02578e46bf
25 changed files with 158 additions and 125 deletions
+35 -42
View File
@@ -18,6 +18,7 @@
#include "precompiled.h"
#include "ScriptContext.h"
#include "ScriptExtraHeaders.h"
#include "ScriptInterface.h"
#include "ScriptStats.h"
@@ -42,8 +43,6 @@
#include "valgrind.h"
#include "scriptinterface/ScriptExtraHeaders.h"
/**
* @file
* Abstractions of various SpiderMonkey features.
@@ -75,8 +74,7 @@ struct ScriptInterface_impl
ScriptRequest::ScriptRequest(const ScriptInterface& scriptInterface) :
cx(scriptInterface.m->m_cx)
{
JS_BeginRequest(cx);
m_formerCompartment = JS_EnterCompartment(cx, scriptInterface.m->m_glob);
m_formerRealm = JS::EnterRealm(cx, scriptInterface.m->m_glob);
glob = JS::CurrentGlobalOrNull(cx);
}
@@ -87,8 +85,7 @@ JS::Value ScriptRequest::globalValue() const
ScriptRequest::~ScriptRequest()
{
JS_LeaveCompartment(cx, m_formerCompartment);
JS_EndRequest(cx);
JS::LeaveRealm(cx, m_formerRealm);
}
namespace
@@ -324,17 +321,16 @@ bool ScriptInterface::MathRandom(double& nbr)
ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const shared_ptr<ScriptContext>& context) :
m_context(context), m_cx(context->GetGeneralJSContext()), m_glob(context->GetGeneralJSContext()), m_nativeScope(context->GetGeneralJSContext())
{
JS::CompartmentCreationOptions creationOpt;
JS::RealmCreationOptions creationOpt;
// Keep JIT code during non-shrinking GCs. This brings a quite big performance improvement.
creationOpt.setPreserveJitCode(true);
JS::CompartmentOptions opt(creationOpt, JS::CompartmentBehaviors{});
JS::RealmOptions opt(creationOpt, JS::RealmBehaviors{});
JSAutoRequest rq(m_cx);
m_glob = JS_NewGlobalObject(m_cx, &global_class, nullptr, JS::OnNewGlobalHookOption::FireOnNewGlobalHook, opt);
JSAutoCompartment autoCmpt(m_cx, m_glob);
JSAutoRealm autoRealm(m_cx, m_glob);
ENSURE(JS_InitStandardClasses(m_cx, m_glob));
ENSURE(JS::InitRealmStandardClasses(m_cx));
JS_DefineProperty(m_cx, m_glob, "global", m_glob, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
@@ -351,18 +347,17 @@ ScriptInterface_impl::ScriptInterface_impl(const char* nativeScopeName, const sh
Register("ProfileStop", ::ProfileStop, 0);
Register("ProfileAttribute", ::ProfileAttribute, 1);
m_context->RegisterCompartment(js::GetObjectCompartment(m_glob));
m_context->RegisterRealm(JS::GetObjectRealmOrNull(m_glob));
}
ScriptInterface_impl::~ScriptInterface_impl()
{
m_context->UnRegisterCompartment(js::GetObjectCompartment(m_glob));
m_context->UnRegisterRealm(JS::GetObjectRealmOrNull(m_glob));
}
void ScriptInterface_impl::Register(const char* name, JSNative fptr, uint nargs) const
{
JSAutoRequest rq(m_cx);
JSAutoCompartment autoCmpt(m_cx, m_glob);
JSAutoRealm autoRealm(m_cx, m_glob);
JS::RootedObject nativeScope(m_cx, m_nativeScope);
JS::RootedFunction func(m_cx, JS_DefineFunction(m_cx, nativeScope, name, fptr, nargs, JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT));
}
@@ -718,7 +713,7 @@ bool ScriptInterface::EnumeratePropertyNames(JS::HandleValue objVal, bool enumer
}
JS::RootedObject obj(rq.cx, &objVal.toObject());
JS::AutoIdVector props(rq.cx);
JS::RootedIdVector props(rq.cx);
// This recurses up the prototype chain on its own.
if (!js::GetPropertyKeys(rq.cx, obj, enumerableOnly? 0 : JSITER_HIDDEN, &props))
return false;
@@ -774,20 +769,20 @@ bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& cod
{
ScriptRequest rq(this);
JS::RootedObject global(rq.cx, rq.glob);
utf16string codeUtf16(code.begin(), code.end());
uint lineNo = 1;
// 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.
std::string filenameStr = filename.string8();
JS::CompileOptions options(rq.cx);
options.setFileAndLine(filenameStr.c_str(), lineNo);
options.setFileAndLine(filenameStr.c_str(), 1);
options.setIsRunOnce(false);
JS::RootedFunction func(rq.cx);
JS::AutoObjectVector emptyScopeChain(rq.cx);
if (!JS::CompileFunction(rq.cx, emptyScopeChain, options, NULL, 0, NULL,
reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &func))
JS::SourceText<mozilla::Utf8Unit> src;
ENSURE(src.init(rq.cx, code.c_str(), code.length(), JS::SourceOwnership::Borrowed));
JS::RootedObjectVector emptyScopeChain(rq.cx);
JS::RootedFunction func(rq.cx, JS::CompileFunction(rq.cx, emptyScopeChain, options, NULL, 0, NULL, src));
if (func == nullptr)
{
ScriptException::CatchPending(rq);
return false;
@@ -801,19 +796,20 @@ bool ScriptInterface::LoadScript(const VfsPath& filename, const std::string& cod
return false;
}
bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::wstring& code) const
bool ScriptInterface::LoadGlobalScript(const VfsPath& filename, const std::string& code) const
{
ScriptRequest rq(this);
utf16string codeUtf16(code.begin(), code.end());
uint lineNo = 1;
// 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.
std::string filenameStr = filename.string8();
JS::RootedValue rval(rq.cx);
JS::CompileOptions opts(rq.cx);
opts.setFileAndLine(filenameStr.c_str(), lineNo);
if (JS::Evaluate(rq.cx, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &rval))
opts.setFileAndLine(filenameStr.c_str(), 1);
JS::SourceText<mozilla::Utf8Unit> src;
ENSURE(src.init(rq.cx, code.c_str(), code.length(), JS::SourceOwnership::Borrowed));
if (JS::Evaluate(rq.cx, opts, src, &rval))
return true;
ScriptException::CatchPending(rq);
@@ -839,9 +835,8 @@ bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) const
return false;
}
std::wstring code = wstring_from_utf8(file.DecodeUTF8()); // assume it's UTF-8
CStr code = file.DecodeUTF8(); // assume it's UTF-8
utf16string codeUtf16(code.begin(), code.end());
uint lineNo = 1;
// 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.
@@ -850,7 +845,9 @@ bool ScriptInterface::LoadGlobalScriptFile(const VfsPath& path) const
JS::RootedValue rval(rq.cx);
JS::CompileOptions opts(rq.cx);
opts.setFileAndLine(filenameStr.c_str(), lineNo);
if (JS::Evaluate(rq.cx, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)(codeUtf16.length()), &rval))
JS::SourceText<mozilla::Utf8Unit> src;
ENSURE(src.init(rq.cx, code.c_str(), code.length(), JS::SourceOwnership::Borrowed));
if (JS::Evaluate(rq.cx, opts, src, &rval))
return true;
ScriptException::CatchPending(rq);
@@ -861,31 +858,27 @@ bool ScriptInterface::Eval(const char* code) const
{
ScriptRequest rq(this);
JS::RootedValue rval(rq.cx);
return Eval_(code, &rval);
}
bool ScriptInterface::Eval_(const char* code, JS::MutableHandleValue rval) const
{
ScriptRequest rq(this);
utf16string codeUtf16(code, code+strlen(code));
JS::CompileOptions opts(rq.cx);
opts.setFileAndLine("(eval)", 1);
if (JS::Evaluate(rq.cx, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)codeUtf16.length(), rval))
JS::SourceText<mozilla::Utf8Unit> src;
ENSURE(src.init(rq.cx, code, strlen(code), JS::SourceOwnership::Borrowed));
if (JS::Evaluate(rq.cx, opts, src, &rval))
return true;
ScriptException::CatchPending(rq);
return false;
}
bool ScriptInterface::Eval_(const wchar_t* code, JS::MutableHandleValue rval) const
bool ScriptInterface::Eval(const char* code, JS::MutableHandleValue rval) const
{
ScriptRequest rq(this);
utf16string codeUtf16(code, code+wcslen(code));
JS::CompileOptions opts(rq.cx);
opts.setFileAndLine("(eval)", 1);
if (JS::Evaluate(rq.cx, opts, reinterpret_cast<const char16_t*>(codeUtf16.c_str()), (uint)codeUtf16.length(), rval))
JS::SourceText<mozilla::Utf8Unit> src;
ENSURE(src.init(rq.cx, code, strlen(code), JS::SourceOwnership::Borrowed));
if (JS::Evaluate(rq.cx, opts, src, rval))
return true;
ScriptException::CatchPending(rq);