зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland. CLOSED TREE
This commit is contained in:
Коммит
3c1bd03590
|
@ -183,6 +183,7 @@
|
|||
#include "nsIURIWithSpecialOrigin.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIWidget.h"
|
||||
#include "nsIWindowMediator.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsJSUtils.h"
|
||||
|
@ -272,7 +273,7 @@ nsIContentPolicy *nsContentUtils::sContentPolicyService;
|
|||
bool nsContentUtils::sTriedToGetContentPolicy = false;
|
||||
RefPtr<mozilla::intl::LineBreaker> nsContentUtils::sLineBreaker;
|
||||
RefPtr<mozilla::intl::WordBreaker> nsContentUtils::sWordBreaker;
|
||||
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nullptr;
|
||||
StaticRefPtr<nsIBidiKeyboard> nsContentUtils::sBidiKeyboard;
|
||||
uint32_t nsContentUtils::sScriptBlockerCount = 0;
|
||||
uint32_t nsContentUtils::sDOMNodeRemovedSuppressCount = 0;
|
||||
AutoTArray<nsCOMPtr<nsIRunnable>, 8>* nsContentUtils::sBlockedScriptRunners = nullptr;
|
||||
|
@ -1633,10 +1634,7 @@ nsIBidiKeyboard*
|
|||
nsContentUtils::GetBidiKeyboard()
|
||||
{
|
||||
if (!sBidiKeyboard) {
|
||||
nsresult rv = CallGetService("@mozilla.org/widget/bidikeyboard;1", &sBidiKeyboard);
|
||||
if (NS_FAILED(rv)) {
|
||||
sBidiKeyboard = nullptr;
|
||||
}
|
||||
sBidiKeyboard = nsIWidget::CreateBidiKeyboard();
|
||||
}
|
||||
return sBidiKeyboard;
|
||||
}
|
||||
|
@ -1986,7 +1984,7 @@ nsContentUtils::Shutdown()
|
|||
NS_IF_RELEASE(sUUIDGenerator);
|
||||
sLineBreaker = nullptr;
|
||||
sWordBreaker = nullptr;
|
||||
NS_IF_RELEASE(sBidiKeyboard);
|
||||
sBidiKeyboard = nullptr;
|
||||
|
||||
delete sAtomEventTable;
|
||||
sAtomEventTable = nullptr;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "mozilla/CORSMode.h"
|
||||
#include "mozilla/EventForwards.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "mozilla/TaskCategory.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsContentListDeclarations.h"
|
||||
|
@ -3449,7 +3450,7 @@ private:
|
|||
static RefPtr<mozilla::intl::LineBreaker> sLineBreaker;
|
||||
static RefPtr<mozilla::intl::WordBreaker> sWordBreaker;
|
||||
|
||||
static nsIBidiKeyboard* sBidiKeyboard;
|
||||
static mozilla::StaticRefPtr<nsIBidiKeyboard> sBidiKeyboard;
|
||||
|
||||
static bool sInitialized;
|
||||
static uint32_t sScriptBlockerCount;
|
||||
|
|
|
@ -298,6 +298,12 @@ nsFocusManager::IsFocused(nsIContent* aContent)
|
|||
return aContent == mFocusedElement;
|
||||
}
|
||||
|
||||
bool
|
||||
nsFocusManager::IsTestMode()
|
||||
{
|
||||
return sTestMode;
|
||||
}
|
||||
|
||||
// get the current window for the given content node
|
||||
static nsPIDOMWindowOuter*
|
||||
GetCurrentWindow(nsIContent* aContent)
|
||||
|
|
|
@ -76,6 +76,11 @@ public:
|
|||
*/
|
||||
bool IsFocused(nsIContent* aContent);
|
||||
|
||||
/**
|
||||
* Returns true if test mode is enabled.
|
||||
*/
|
||||
bool IsTestMode();
|
||||
|
||||
/**
|
||||
* Return a focused window. Version of nsIFocusManager::GetFocusedWindow.
|
||||
*/
|
||||
|
|
|
@ -74,7 +74,6 @@ WebCryptoThreadPool::DispatchInternal(nsIRunnable* aRunnable)
|
|||
NS_ENSURE_TRUE(EnsureNSSInitializedChromeOrContent(), NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIThreadPool> pool(new nsThreadPool());
|
||||
NS_ENSURE_TRUE(pool, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult rv = pool->SetName(NS_LITERAL_CSTRING("SubtleCrypto"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
|
|
@ -13,7 +13,6 @@ XPIDL_SOURCES += [
|
|||
'nsIDOMXULContainerElement.idl',
|
||||
'nsIDOMXULControlElement.idl',
|
||||
'nsIDOMXULLabeledControlEl.idl',
|
||||
'nsIDOMXULLabelElement.idl',
|
||||
'nsIDOMXULMenuListElement.idl',
|
||||
'nsIDOMXULMultSelectCntrlEl.idl',
|
||||
'nsIDOMXULRelatedElement.idl',
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
[scriptable, uuid(8b67286b-bf86-4808-8a68-ecdbc7d9877b)]
|
||||
interface nsIDOMXULLabelElement : nsISupports {
|
||||
attribute DOMString accessKey;
|
||||
attribute DOMString control;
|
||||
};
|
|
@ -41,10 +41,6 @@ class IpcResourceUpdateQueue;
|
|||
#define NS_ITHEME_IID \
|
||||
{ 0x7329f760, 0x08cb, 0x450f, \
|
||||
{ 0x82, 0x25, 0xda, 0xe7, 0x29, 0x09, 0x6d, 0xec } }
|
||||
// {0ae05515-cf7a-45a8-9e02-6556de7685b1}
|
||||
#define NS_THEMERENDERER_CID \
|
||||
{ 0x0ae05515, 0xcf7a, 0x45a8, \
|
||||
{ 0x9e, 0x02, 0x65, 0x56, 0xde, 0x76, 0x85, 0xb1 } }
|
||||
|
||||
/**
|
||||
* nsITheme is a service that provides platform-specific native
|
||||
|
@ -233,6 +229,6 @@ public:
|
|||
NS_DEFINE_STATIC_IID_ACCESSOR(nsITheme, NS_ITHEME_IID)
|
||||
|
||||
// Creator function
|
||||
extern nsresult NS_NewNativeTheme(nsISupports *aOuter, REFNSIID aIID, void **aResult);
|
||||
extern already_AddRefed<nsITheme> NS_NewNativeTheme();
|
||||
|
||||
#endif
|
||||
|
|
|
@ -162,7 +162,7 @@ Load(JSContext *cx,
|
|||
options.setUTF8(true)
|
||||
.setFileAndLine(filename.get(), 1);
|
||||
JS::Rooted<JSScript*> script(cx);
|
||||
bool ok = JS::Compile(cx, options, file, &script);
|
||||
bool ok = JS::CompileUtf8File(cx, options, file, &script);
|
||||
fclose(file);
|
||||
if (!ok)
|
||||
return false;
|
||||
|
@ -304,7 +304,7 @@ XPCShellEnvironment::ProcessFile(JSContext *cx,
|
|||
options.setUTF8(true)
|
||||
.setFileAndLine(filename, 1);
|
||||
JS::Rooted<JSScript*> script(cx);
|
||||
if (JS::Compile(cx, options, file, &script))
|
||||
if (JS::CompileUtf8File(cx, options, file, &script))
|
||||
(void)JS_ExecuteScript(cx, script, &result);
|
||||
|
||||
return;
|
||||
|
|
|
@ -86,7 +86,7 @@ JS_ExecuteScript(JSContext* cx, JS::AutoVector<JSObject*>& envChain, JS::Handle<
|
|||
* |script| will always be set. On failure, it will be set to nullptr.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
|
||||
JS_CompileScript(JSContext* cx, const char* bytes, size_t length,
|
||||
const JS::CompileOptions& options,
|
||||
JS::MutableHandle<JSScript*> script);
|
||||
|
||||
|
@ -152,33 +152,106 @@ extern JS_PUBLIC_API(bool)
|
|||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, MutableHandle<JSScript*> script);
|
||||
|
||||
/**
|
||||
* Compile the provided UTF-8 data into a script. If the data contains invalid
|
||||
* UTF-8, an error is reported.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be true. At a future time this flag
|
||||
* will be removed and UTF-8-ness of source bytes will be entirely determined
|
||||
* by which compilation function is called.
|
||||
*
|
||||
* |script| is always set to the compiled script or to null in case of error.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, MutableHandle<JSScript*> script);
|
||||
CompileUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, MutableHandle<JSScript*> script);
|
||||
|
||||
/**
|
||||
* Compile the provided Latin-1 data (i.e. each byte directly corresponds to
|
||||
* the same Unicode code point) into a script.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be false. At a future time this flag
|
||||
* will be removed and UTF-8-ness of source bytes will be entirely determined
|
||||
* by which compilation function is called.
|
||||
*
|
||||
* This function may eventually be removed, such that *only* bytes containing
|
||||
* UTF-8 source text may be directly compiled. Avoid using it if you can.
|
||||
*
|
||||
* |script| is always set to the compiled script or to null in case of error.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
FILE* file, MutableHandle<JSScript*> script);
|
||||
CompileLatin1(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, MutableHandle<JSScript*> script);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
/**
|
||||
* DEPRECATED
|
||||
*
|
||||
* Compile the provided bytes into a script.
|
||||
*
|
||||
* If |options.utf8|, the bytes are interpreted as UTF-8 data. If the data
|
||||
* contains any malformed UTF-8, an error is reported.
|
||||
*
|
||||
* Otherwise they are interpreted as Latin-1, i.e. each byte directly
|
||||
* corresponds to the same Unicode code point.
|
||||
*
|
||||
* |script| is always set to the compiled script or to null in case of error.
|
||||
*
|
||||
* Do not use this API. The JS::CompileOptions::utf8 flag that indicates how
|
||||
* to interpret |bytes| is currently being replaced by functions indicating an
|
||||
* exact expected encoding. If you have byte data to compile, you should use
|
||||
* either JS::CompileUtf8 or JS::CompileLatin1, as appropriate.
|
||||
*/
|
||||
inline bool
|
||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* filename, MutableHandle<JSScript*> script);
|
||||
const char* bytes, size_t length, MutableHandle<JSScript*> script)
|
||||
{
|
||||
return options.utf8
|
||||
? CompileUtf8(cx, options, bytes, length, script)
|
||||
: CompileLatin1(cx, options, bytes, length, script);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile the UTF-8 contents of the given file into a script. If the contents
|
||||
* contain any malformed UTF-8, an error is reported.
|
||||
*
|
||||
* |script| is always set to the compiled script or to null in case of error.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be true. At a future time this flag
|
||||
* will be removed.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileUtf8File(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
FILE* file, MutableHandle<JSScript*> script);
|
||||
|
||||
/**
|
||||
* Compile the UTF-8 contents of the file at the given path into a script.
|
||||
* (The path itself is in the system encoding, not [necessarily] UTF-8.) If
|
||||
* the contents contain any malformed UTF-8, an error is reported.
|
||||
*
|
||||
* |script| is always set to the compiled script or to null in case of error.
|
||||
*
|
||||
* The |options.utf8| flag is asserted to be true. At a future time this flag
|
||||
* will be removed.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileUtf8Path(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* filename, MutableHandle<JSScript*> script);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, MutableHandle<JSScript*> script);
|
||||
|
||||
/**
|
||||
* Compile the given Latin-1 data for non-syntactic scope.
|
||||
*
|
||||
* There is no way to compile UTF-8 data for non-syntactic scope because no
|
||||
* user currently needs it. Such way could be added in the future if it's ever
|
||||
* needed.
|
||||
*/
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, MutableHandle<JSScript*> script);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
FILE* file, MutableHandle<JSScript*> script);
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* filename, MutableHandle<JSScript*> script);
|
||||
CompileLatin1ForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length,
|
||||
MutableHandle<JSScript*> script);
|
||||
|
||||
/**
|
||||
* Compile a function with envChain plus the global as its scope chain.
|
||||
|
|
|
@ -109,6 +109,13 @@ FinishMultiOffThreadScriptsDecoder(JSContext* cx, OffThreadToken* token,
|
|||
extern JS_PUBLIC_API(void)
|
||||
CancelMultiOffThreadScriptsDecoder(JSContext* cx, OffThreadToken* token);
|
||||
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
CanDecodeBinASTOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length);
|
||||
|
||||
#endif // defined(JS_BUILD_BINAST)
|
||||
|
||||
} // namespace JS
|
||||
|
||||
#endif /* js_OffThreadScriptCompilation_h */
|
||||
|
|
|
@ -85,7 +85,7 @@ testCompile(bool nonSyntactic)
|
|||
CHECK(CompileForNonSyntacticScope(cx, options, buf, &script));
|
||||
CHECK_EQUAL(script->hasNonSyntacticScope(), true);
|
||||
|
||||
CHECK(CompileForNonSyntacticScope(cx, options, src, length, &script));
|
||||
CHECK(CompileLatin1ForNonSyntacticScope(cx, options, src, length, &script));
|
||||
CHECK_EQUAL(script->hasNonSyntacticScope(), true);
|
||||
|
||||
{
|
||||
|
|
|
@ -28,7 +28,7 @@ BEGIN_TEST(testExecuteInJSMEnvironment_Basic)
|
|||
options.setNoScriptRval(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::CompileForNonSyntacticScope(cx, options, src, sizeof(src)-1, &script));
|
||||
CHECK(JS::CompileLatin1ForNonSyntacticScope(cx, options, src, sizeof(src) - 1, &script));
|
||||
|
||||
JS::RootedObject varEnv(cx, js::NewJSMEnvironment(cx));
|
||||
JS::RootedObject lexEnv(cx, JS_ExtensibleLexicalEnvironment(varEnv));
|
||||
|
@ -88,7 +88,7 @@ BEGIN_TEST(testExecuteInJSMEnvironment_Callback)
|
|||
options.setNoScriptRval(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::CompileForNonSyntacticScope(cx, options, src, sizeof(src)-1, &script));
|
||||
CHECK(JS::CompileLatin1ForNonSyntacticScope(cx, options, src, sizeof(src) - 1, &script));
|
||||
|
||||
JS::RootedObject nsvo(cx, js::NewJSMEnvironment(cx));
|
||||
CHECK(nsvo);
|
||||
|
|
|
@ -110,10 +110,14 @@ BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile)
|
|||
FILE* script_stream = tempScript.open(script_filename);
|
||||
CHECK(fputs(code, script_stream) != EOF);
|
||||
tempScript.close();
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(script_filename, 1);
|
||||
options.setUTF8(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::Compile(cx, options, script_filename, &script));
|
||||
CHECK(JS::CompileUtf8Path(cx, options, script_filename, &script));
|
||||
|
||||
tempScript.remove();
|
||||
return tryScript(script);
|
||||
}
|
||||
|
@ -125,10 +129,14 @@ BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
|
|||
static const char script_filename[] = "temp-bug438633_JS_CompileFile_empty";
|
||||
tempScript.open(script_filename);
|
||||
tempScript.close();
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(script_filename, 1);
|
||||
options.setUTF8(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::Compile(cx, options, script_filename, &script));
|
||||
CHECK(JS::CompileUtf8Path(cx, options, script_filename, &script));
|
||||
|
||||
tempScript.remove();
|
||||
return tryScript(script);
|
||||
}
|
||||
|
@ -136,28 +144,32 @@ END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFile_empty)
|
|||
|
||||
BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle)
|
||||
{
|
||||
const char* script_filename = "temporary file";
|
||||
TempFile tempScript;
|
||||
FILE* script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandle");
|
||||
CHECK(fputs(code, script_stream) != EOF);
|
||||
CHECK(fseek(script_stream, 0, SEEK_SET) != EOF);
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(script_filename, 1);
|
||||
options.setFileAndLine("temporary file", 1);
|
||||
options.setUTF8(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::Compile(cx, options, script_stream, &script));
|
||||
CHECK(JS::CompileUtf8File(cx, options, script_stream, &script));
|
||||
return tryScript(script);
|
||||
}
|
||||
END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle)
|
||||
|
||||
BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle_empty)
|
||||
{
|
||||
const char* script_filename = "empty temporary file";
|
||||
TempFile tempScript;
|
||||
FILE* script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandle_empty");
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine(script_filename, 1);
|
||||
options.setFileAndLine("empty temporary file", 1);
|
||||
options.setUTF8(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::Compile(cx, options, script_stream, &script));
|
||||
CHECK(JS::CompileUtf8File(cx, options, script_stream, &script));
|
||||
return tryScript(script);
|
||||
}
|
||||
END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandle_empty)
|
||||
|
@ -168,10 +180,13 @@ BEGIN_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandleForPrincip
|
|||
FILE* script_stream = tempScript.open("temp-bug438633_JS_CompileFileHandleForPrincipals");
|
||||
CHECK(fputs(code, script_stream) != EOF);
|
||||
CHECK(fseek(script_stream, 0, SEEK_SET) != EOF);
|
||||
|
||||
JS::CompileOptions options(cx);
|
||||
options.setFileAndLine("temporary file", 1);
|
||||
options.setUTF8(true);
|
||||
|
||||
JS::RootedScript script(cx);
|
||||
CHECK(JS::Compile(cx, options, script_stream, &script));
|
||||
CHECK(JS::CompileUtf8File(cx, options, script_stream, &script));
|
||||
return tryScript(script);
|
||||
}
|
||||
END_FIXTURE_TEST(ScriptObjectFixture, bug438633_JS_CompileFileHandleForPrincipals)
|
||||
|
|
887
js/src/jsapi.cpp
887
js/src/jsapi.cpp
|
@ -21,7 +21,6 @@
|
|||
#endif
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "jsdate.h"
|
||||
#include "jsexn.h"
|
||||
|
@ -46,8 +45,6 @@
|
|||
# include "builtin/TypedObject.h"
|
||||
#endif
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "frontend/FullParseHandler.h" // for JS_BufferIsCompileableUnit
|
||||
#include "frontend/Parser.h" // for JS_BufferIsCompileableUnit
|
||||
#include "gc/FreeOp.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/Policy.h"
|
||||
|
@ -70,6 +67,7 @@
|
|||
#include "js/StructuredClone.h"
|
||||
#include "js/Utility.h"
|
||||
#include "js/Wrapper.h"
|
||||
#include "util/CompleteFile.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
|
@ -3613,51 +3611,6 @@ JS::NewFunctionFromSpec(JSContext* cx, const JSFunctionSpec* fs, HandleId id)
|
|||
return fun;
|
||||
}
|
||||
|
||||
static bool
|
||||
CreateNonSyntacticEnvironmentChain(JSContext* cx, AutoObjectVector& envChain,
|
||||
MutableHandleObject env, MutableHandleScope scope)
|
||||
{
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
if (!js::CreateObjectsForEnvironmentChain(cx, envChain, globalLexical, env)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!envChain.empty()) {
|
||||
scope.set(GlobalScope::createEmpty(cx, ScopeKind::NonSyntactic));
|
||||
if (!scope) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The XPConnect subscript loader, which may pass in its own
|
||||
// environments to load scripts in, expects the environment chain to
|
||||
// be the holder of "var" declarations. In SpiderMonkey, such objects
|
||||
// are called "qualified varobjs", the "qualified" part meaning the
|
||||
// declaration was qualified by "var". There is only sadness.
|
||||
//
|
||||
// See JSObject::isQualifiedVarObj.
|
||||
if (!JSObject::setQualifiedVarObj(cx, env)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Also get a non-syntactic lexical environment to capture 'let' and
|
||||
// 'const' bindings. To persist lexical bindings, we have a 1-1
|
||||
// mapping with the final unwrapped environment object (the
|
||||
// environment that stores the 'var' bindings) and the lexical
|
||||
// environment.
|
||||
//
|
||||
// TODOshu: disallow the subscript loader from using non-distinguished
|
||||
// objects as dynamic scopes.
|
||||
env.set(ObjectRealm::get(env).getOrCreateNonSyntacticLexicalEnvironment(cx, env));
|
||||
if (!env) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
scope.set(&cx->global()->emptyGlobalScope());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsFunctionCloneable(HandleFunction fun)
|
||||
{
|
||||
|
@ -3872,99 +3825,6 @@ JS_DefineFunctionById(JSContext* cx, HandleObject obj, HandleId id, JSNative cal
|
|||
return DefineFunction(cx, obj, id, call, nargs, attrs);
|
||||
}
|
||||
|
||||
/* Use the fastest available getc. */
|
||||
#if defined(HAVE_GETC_UNLOCKED)
|
||||
# define fast_getc getc_unlocked
|
||||
#elif defined(HAVE__GETC_NOLOCK)
|
||||
# define fast_getc _getc_nolock
|
||||
#else
|
||||
# define fast_getc getc
|
||||
#endif
|
||||
|
||||
using FileContents = Vector<uint8_t, 8, TempAllocPolicy>;
|
||||
|
||||
static bool
|
||||
ReadCompleteFile(JSContext* cx, FILE* fp, FileContents& buffer)
|
||||
{
|
||||
/* Get the complete length of the file, if possible. */
|
||||
struct stat st;
|
||||
int ok = fstat(fileno(fp), &st);
|
||||
if (ok != 0) {
|
||||
return false;
|
||||
}
|
||||
if (st.st_size > 0) {
|
||||
if (!buffer.reserve(st.st_size)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Read in the whole file. Note that we can't assume the data's length
|
||||
// is actually st.st_size, because 1) some files lie about their size
|
||||
// (/dev/zero and /dev/random), and 2) reading files in text mode on
|
||||
// Windows collapses "\r\n" pairs to single \n characters.
|
||||
for (;;) {
|
||||
int c = fast_getc(fp);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (!buffer.append(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class AutoFile
|
||||
{
|
||||
FILE* fp_;
|
||||
public:
|
||||
AutoFile()
|
||||
: fp_(nullptr)
|
||||
{}
|
||||
~AutoFile()
|
||||
{
|
||||
if (fp_ && fp_ != stdin) {
|
||||
fclose(fp_);
|
||||
}
|
||||
}
|
||||
FILE* fp() const { return fp_; }
|
||||
bool open(JSContext* cx, const char* filename);
|
||||
bool readAll(JSContext* cx, FileContents& buffer)
|
||||
{
|
||||
MOZ_ASSERT(fp_);
|
||||
return ReadCompleteFile(cx, fp_, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
||||
/*
|
||||
* Open a source file for reading. Supports "-" and nullptr to mean stdin. The
|
||||
* return value must be fclosed unless it is stdin.
|
||||
*/
|
||||
bool
|
||||
AutoFile::open(JSContext* cx, const char* filename)
|
||||
{
|
||||
if (!filename || strcmp(filename, "-") == 0) {
|
||||
fp_ = stdin;
|
||||
} else {
|
||||
fp_ = fopen(filename, "r");
|
||||
if (!fp_) {
|
||||
/*
|
||||
* Use Latin1 variant here because the encoding of filename is
|
||||
* platform dependent.
|
||||
*/
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_CANT_OPEN,
|
||||
filename, "No such file or directory");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JS::TransitiveCompileOptions::copyPODTransitiveOptions(const TransitiveCompileOptions& rhs)
|
||||
{
|
||||
|
@ -4120,127 +3980,6 @@ JS::CompileOptions::CompileOptions(JSContext* cx)
|
|||
throwOnAsmJSValidationFailureOption = cx->options().throwOnAsmJSValidationFailure();
|
||||
}
|
||||
|
||||
static bool
|
||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, MutableHandleScript script)
|
||||
{
|
||||
ScopeKind scopeKind = options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global;
|
||||
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf));
|
||||
return !!script;
|
||||
}
|
||||
|
||||
static bool
|
||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, MutableHandleScript script)
|
||||
{
|
||||
char16_t* chars;
|
||||
if (options.utf8) {
|
||||
chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
|
||||
} else {
|
||||
chars = InflateString(cx, bytes, length);
|
||||
}
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
|
||||
return ::Compile(cx, options, source, script);
|
||||
}
|
||||
|
||||
static bool
|
||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
FILE* fp, MutableHandleScript script)
|
||||
{
|
||||
FileContents buffer(cx);
|
||||
if (!ReadCompleteFile(cx, fp, buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ::Compile(cx, options, reinterpret_cast<const char*>(buffer.begin()), buffer.length(), script);
|
||||
}
|
||||
|
||||
static bool
|
||||
Compile(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* filename, MutableHandleScript script)
|
||||
{
|
||||
AutoFile file;
|
||||
if (!file.open(cx, filename)) {
|
||||
return false;
|
||||
}
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setFileAndLine(filename, 1);
|
||||
return ::Compile(cx, options, file.fp(), script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
|
||||
{
|
||||
return ::Compile(cx, options, srcBuf, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, JS::MutableHandleScript script)
|
||||
{
|
||||
return ::Compile(cx, options, bytes, length, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
FILE* file, JS::MutableHandleScript script)
|
||||
{
|
||||
return ::Compile(cx, options, file, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* filename, JS::MutableHandleScript script)
|
||||
{
|
||||
return ::Compile(cx, options, filename, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
|
||||
{
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setNonSyntacticScope(true);
|
||||
return ::Compile(cx, options, srcBuf, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* bytes, size_t length, JS::MutableHandleScript script)
|
||||
{
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setNonSyntacticScope(true);
|
||||
return ::Compile(cx, options, bytes, length, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
FILE* file, JS::MutableHandleScript script)
|
||||
{
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setNonSyntacticScope(true);
|
||||
return ::Compile(cx, options, file, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* filename, JS::MutableHandleScript script)
|
||||
{
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setNonSyntacticScope(true);
|
||||
return ::Compile(cx, options, filename, script);
|
||||
}
|
||||
|
||||
#if defined(JS_BUILD_BINAST)
|
||||
|
||||
JSScript*
|
||||
|
@ -4280,256 +4019,8 @@ JS::FinishOffThreadBinASTDecode(JSContext* cx, JS::OffThreadToken* token)
|
|||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishBinASTDecodeTask(cx, token);
|
||||
}
|
||||
|
||||
#endif /* JS_BUILD_BINAST */
|
||||
|
||||
enum class OffThread {
|
||||
Compile, Decode, DecodeBinAST
|
||||
};
|
||||
|
||||
static bool
|
||||
CanDoOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length, OffThread what)
|
||||
{
|
||||
static const size_t TINY_LENGTH = 5 * 1000;
|
||||
static const size_t HUGE_SRC_LENGTH = 100 * 1000;
|
||||
static const size_t HUGE_BC_LENGTH = 367 * 1000;
|
||||
static const size_t HUGE_BINAST_LENGTH = 70 * 1000;
|
||||
|
||||
// TODO: We can't decode BinAST off main thread until bug 1459555 is fixed.
|
||||
if (what == OffThread::DecodeBinAST) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// These are heuristics which the caller may choose to ignore (e.g., for
|
||||
// testing purposes).
|
||||
if (!options.forceAsync) {
|
||||
// Compiling off the main thread inolves creating a new Zone and other
|
||||
// significant overheads. Don't bother if the script is tiny.
|
||||
if (length < TINY_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the parsing task would have to wait for GC to complete, it'll probably
|
||||
// be faster to just start it synchronously on the main thread unless the
|
||||
// script is huge.
|
||||
if (OffThreadParsingMustWaitForGC(cx->runtime())) {
|
||||
if (what == OffThread::Compile && length < HUGE_SRC_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
if (what == OffThread::Decode && length < HUGE_BC_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
if (what == OffThread::DecodeBinAST && length < HUGE_BINAST_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cx->runtime()->canUseParallelParsing() &&
|
||||
CanUseExtraThreads() &&
|
||||
!mozilla::recordreplay::IsRecordingOrReplaying();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
|
||||
{
|
||||
return CanDoOffThread(cx, options, length, OffThread::Compile);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CanDecodeOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
|
||||
{
|
||||
return CanDoOffThread(cx, options, length, OffThread::Decode);
|
||||
}
|
||||
|
||||
#ifdef JS_BUILD_BINAST
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CanDecodeBinASTOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
|
||||
{
|
||||
return CanDoOffThread(cx, options, length, OffThread::DecodeBinAST);
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
MOZ_ASSERT(CanCompileOffThread(cx, options, srcBuf.length()));
|
||||
return StartOffThreadParseScript(cx, options, srcBuf, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript*)
|
||||
JS::FinishOffThreadScript(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishScriptParseTask(cx, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelOffThreadScript(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::Script, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
MOZ_ASSERT(CanCompileOffThread(cx, options, srcBuf.length()));
|
||||
return StartOffThreadParseModule(cx, options, srcBuf, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript*)
|
||||
JS::FinishOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishModuleParseTask(cx, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::Module, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
JS::TranscodeRange range(buffer.begin() + cursor, buffer.length() - cursor);
|
||||
MOZ_ASSERT(CanDecodeOffThread(cx, options, range.length()));
|
||||
return StartOffThreadDecodeScript(cx, options, range, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const mozilla::Range<uint8_t>& range /* TranscodeRange& */,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
MOZ_ASSERT(CanDecodeOffThread(cx, options, range.length()));
|
||||
return StartOffThreadDecodeScript(cx, options, range, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::DecodeMultiOffThreadScripts(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
TranscodeSources& sources,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
size_t length = 0;
|
||||
for (auto& source : sources) {
|
||||
length += source.range.length();
|
||||
}
|
||||
MOZ_ASSERT(CanCompileOffThread(cx, options, length));
|
||||
#endif
|
||||
return StartOffThreadDecodeMultiScripts(cx, options, sources, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript*)
|
||||
JS::FinishOffThreadScriptDecoder(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishScriptDecodeTask(cx, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelOffThreadScriptDecoder(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::ScriptDecode, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::FinishMultiOffThreadScriptsDecoder(JSContext* cx, JS::OffThreadToken* token, MutableHandle<ScriptVector> scripts)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishMultiScriptsDecodeTask(cx, token, scripts);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelMultiOffThreadScriptsDecoder(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::MultiScriptsDecode, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_CompileScript(JSContext* cx, const char* ascii, size_t length,
|
||||
const JS::CompileOptions& options, MutableHandleScript script)
|
||||
{
|
||||
return ::Compile(cx, options, ascii, length, script);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_CompileUCScript(JSContext* cx, JS::SourceBufferHolder& srcBuf,
|
||||
const JS::CompileOptions& options, MutableHandleScript script)
|
||||
{
|
||||
return ::Compile(cx, options, srcBuf, script);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, size_t length)
|
||||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(obj);
|
||||
|
||||
cx->clearPendingException();
|
||||
|
||||
UniqueTwoByteChars chars
|
||||
{ JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get() };
|
||||
if (!chars) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true on any out-of-memory error or non-EOF-related syntax error, so our
|
||||
// caller doesn't try to collect more buffered source.
|
||||
bool result = true;
|
||||
|
||||
CompileOptions options(cx);
|
||||
frontend::UsedNameTracker usedNames(cx);
|
||||
|
||||
RootedScriptSourceObject sourceObject(cx, frontend::CreateScriptSourceObject(cx, options,
|
||||
mozilla::Nothing()));
|
||||
if (!sourceObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
frontend::Parser<frontend::FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(),
|
||||
options, chars.get(), length,
|
||||
/* foldConstants = */ true,
|
||||
usedNames, nullptr, nullptr,
|
||||
sourceObject,
|
||||
frontend::ParseGoal::Script);
|
||||
JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
|
||||
if (!parser.checkOptions() || !parser.parse()) {
|
||||
// We ran into an error. If it was because we ran out of source, we
|
||||
// return false so our caller knows to try to collect more buffered
|
||||
// source.
|
||||
if (parser.isUnexpectedEOF()) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
cx->clearPendingException();
|
||||
}
|
||||
JS::SetWarningReporter(cx, older);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSObject*)
|
||||
JS_GetGlobalFromScript(JSScript* script)
|
||||
{
|
||||
|
@ -4569,191 +4060,6 @@ JS_GetFunctionScript(JSContext* cx, HandleFunction fun)
|
|||
return fun->nonLazyScript();
|
||||
}
|
||||
|
||||
/*
|
||||
* enclosingScope is a scope, if any (e.g. a WithScope). If the scope is the
|
||||
* global scope, this must be null.
|
||||
*
|
||||
* enclosingEnv is an environment to use, if it's not the global.
|
||||
*/
|
||||
static bool
|
||||
CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
HandleAtom name, bool isInvalidName,
|
||||
SourceBufferHolder& srcBuf, uint32_t parameterListEnd,
|
||||
HandleObject enclosingEnv, HandleScope enclosingScope,
|
||||
MutableHandleFunction fun)
|
||||
{
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(enclosingEnv);
|
||||
RootedAtom funAtom(cx);
|
||||
|
||||
fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL,
|
||||
isInvalidName ? nullptr : name,
|
||||
/* proto = */ nullptr,
|
||||
gc::AllocKind::FUNCTION, TenuredObject,
|
||||
enclosingEnv));
|
||||
if (!fun) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the static scope chain matches up when we have a
|
||||
// non-syntactic scope.
|
||||
MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(enclosingEnv),
|
||||
enclosingScope->hasOnChain(ScopeKind::NonSyntactic));
|
||||
|
||||
if (!frontend::CompileStandaloneFunction(cx, fun, optionsArg, srcBuf,
|
||||
Some(parameterListEnd), enclosingScope))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// When function name is not valid identifier, generated function source
|
||||
// in srcBuf doesn't have function name. Set it here.
|
||||
if (isInvalidName) {
|
||||
fun->setAtom(name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
BuildFunctionString(const char* name, size_t nameLen,
|
||||
unsigned nargs, const char* const* argnames,
|
||||
const SourceBufferHolder& srcBuf, StringBuffer* out,
|
||||
uint32_t* parameterListEnd)
|
||||
{
|
||||
MOZ_ASSERT(out);
|
||||
MOZ_ASSERT(parameterListEnd);
|
||||
|
||||
if (!out->ensureTwoByteChars()) {
|
||||
return false;
|
||||
}
|
||||
if (!out->append("function ")) {
|
||||
return false;
|
||||
}
|
||||
if (name) {
|
||||
if (!out->append(name, nameLen)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!out->append("(")) {
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = 0; i < nargs; i++) {
|
||||
if (i != 0) {
|
||||
if (!out->append(", ")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!out->append(argnames[i], strlen(argnames[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remember the position of ")".
|
||||
*parameterListEnd = out->length();
|
||||
MOZ_ASSERT(FunctionConstructorMedialSigils[0] == ')');
|
||||
|
||||
if (!out->append(FunctionConstructorMedialSigils)) {
|
||||
return false;
|
||||
}
|
||||
if (!out->append(srcBuf.get(), srcBuf.length())) {
|
||||
return false;
|
||||
}
|
||||
if (!out->append(FunctionConstructorFinalBrace)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
const char* name, unsigned nargs, const char* const* argnames,
|
||||
SourceBufferHolder& srcBuf, MutableHandleFunction fun)
|
||||
{
|
||||
RootedObject env(cx);
|
||||
RootedScope scope(cx);
|
||||
if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t nameLen = 0;
|
||||
bool isInvalidName = false;
|
||||
RootedAtom nameAtom(cx);
|
||||
if (name) {
|
||||
nameLen = strlen(name);
|
||||
nameAtom = Atomize(cx, name, nameLen);
|
||||
if (!nameAtom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If name is not valid identifier
|
||||
if (!js::frontend::IsIdentifier(name, nameLen)) {
|
||||
isInvalidName = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t parameterListEnd;
|
||||
StringBuffer funStr(cx);
|
||||
if (!BuildFunctionString(isInvalidName ? nullptr : name, nameLen, nargs, argnames, srcBuf,
|
||||
&funStr, ¶meterListEnd))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t newLen = funStr.length();
|
||||
SourceBufferHolder newSrcBuf(funStr.stealChars(), newLen, SourceBufferHolder::GiveOwnership);
|
||||
|
||||
return CompileFunction(cx, options, nameAtom, isInvalidName, newSrcBuf, parameterListEnd, env,
|
||||
scope, fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
const char* name, unsigned nargs, const char* const* argnames,
|
||||
const char* bytes, size_t length, MutableHandleFunction fun)
|
||||
{
|
||||
char16_t* chars;
|
||||
if (options.utf8) {
|
||||
chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
|
||||
} else {
|
||||
chars = InflateString(cx, bytes, length);
|
||||
}
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
|
||||
return CompileFunction(cx, envChain, options, name, nargs, argnames,
|
||||
source, fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::InitScriptSourceElement(JSContext* cx, HandleScript script,
|
||||
HandleObject element, HandleString elementAttrName)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
|
||||
RootedScriptSourceObject sso(cx, &script->sourceObject()->as<ScriptSourceObject>());
|
||||
return ScriptSourceObject::initElementProperties(cx, sso, element, elementAttrName);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::ExposeScriptToDebugger(JSContext* cx, HandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
|
||||
MOZ_ASSERT(script->hideScriptFromDebugger());
|
||||
script->clearHideScriptFromDebugger();
|
||||
Debugger::onNewScript(cx, script);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSString*)
|
||||
JS_DecompileScript(JSContext* cx, HandleScript script)
|
||||
{
|
||||
|
@ -4784,197 +4090,6 @@ JS_DecompileFunction(JSContext* cx, HandleFunction fun)
|
|||
return FunctionToString(cx, fun, /* isToSource = */ false);
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE static bool
|
||||
ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, Value* rval)
|
||||
{
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(scope, script);
|
||||
MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(scope), script->hasNonSyntacticScope());
|
||||
return Execute(cx, script, *scope, rval);
|
||||
}
|
||||
|
||||
static bool
|
||||
ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg, Value* rval)
|
||||
{
|
||||
RootedObject env(cx);
|
||||
RootedScope dummy(cx);
|
||||
if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &dummy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedScript script(cx, scriptArg);
|
||||
if (!script->hasNonSyntacticScope() && !IsGlobalLexicalEnvironment(env)) {
|
||||
script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
js::Debugger::onNewScript(cx, script);
|
||||
}
|
||||
|
||||
return ExecuteScript(cx, env, script, rval);
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||
JS_ExecuteScript(JSContext* cx, HandleScript scriptArg, MutableHandleValue rval)
|
||||
{
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
return ExecuteScript(cx, globalLexical, scriptArg, rval.address());
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||
JS_ExecuteScript(JSContext* cx, HandleScript scriptArg)
|
||||
{
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
return ExecuteScript(cx, globalLexical, scriptArg, nullptr);
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||
JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain,
|
||||
HandleScript scriptArg, MutableHandleValue rval)
|
||||
{
|
||||
return ExecuteScript(cx, envChain, scriptArg, rval.address());
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||
JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg)
|
||||
{
|
||||
return ExecuteScript(cx, envChain, scriptArg, nullptr);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg,
|
||||
JS::MutableHandleValue rval)
|
||||
{
|
||||
CHECK_THREAD(cx);
|
||||
RootedScript script(cx, scriptArg);
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
if (script->realm() != cx->realm()) {
|
||||
script = CloneGlobalScript(cx, ScopeKind::Global, script);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
||||
js::Debugger::onNewScript(cx, script);
|
||||
}
|
||||
return ExecuteScript(cx, globalLexical, script, rval.address());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CloneAndExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain,
|
||||
HandleScript scriptArg,
|
||||
JS::MutableHandleValue rval)
|
||||
{
|
||||
CHECK_THREAD(cx);
|
||||
RootedScript script(cx, scriptArg);
|
||||
if (script->realm() != cx->realm()) {
|
||||
script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
||||
js::Debugger::onNewScript(cx, script);
|
||||
}
|
||||
return ExecuteScript(cx, envChain, script, rval.address());
|
||||
}
|
||||
|
||||
static bool
|
||||
Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
|
||||
const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||
{
|
||||
CompileOptions options(cx, optionsArg);
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(env);
|
||||
MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(env), scopeKind == ScopeKind::NonSyntactic);
|
||||
|
||||
options.setIsRunOnce(true);
|
||||
RootedScript script(cx, frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(),
|
||||
scopeKind, options, srcBuf));
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = Execute(cx, script, *env,
|
||||
options.noScriptRval ? nullptr : rval.address());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||
{
|
||||
RootedObject env(cx);
|
||||
RootedScope scope(cx);
|
||||
if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope)) {
|
||||
return false;
|
||||
}
|
||||
return ::Evaluate(cx, scope->kind(), env, optionsArg, srcBuf, rval);
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, MutableHandleValue rval)
|
||||
{
|
||||
char16_t* chars;
|
||||
if (options.utf8) {
|
||||
chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
|
||||
} else {
|
||||
chars = InflateString(cx, bytes, length);
|
||||
}
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
bool ok = ::Evaluate(cx, ScopeKind::Global, globalLexical, options, srcBuf, rval);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool
|
||||
Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* filename, MutableHandleValue rval)
|
||||
{
|
||||
FileContents buffer(cx);
|
||||
{
|
||||
AutoFile file;
|
||||
if (!file.open(cx, filename) || !file.readAll(cx, buffer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setFileAndLine(filename, 1);
|
||||
return Evaluate(cx, options, reinterpret_cast<const char*>(buffer.begin()), buffer.length(), rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||
{
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||
{
|
||||
return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* filename, MutableHandleValue rval)
|
||||
{
|
||||
return ::Evaluate(cx, optionsArg, filename, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JS::ModuleResolveHook)
|
||||
JS::GetModuleResolveHook(JSRuntime* rt)
|
||||
{
|
||||
|
|
|
@ -353,6 +353,7 @@ UNIFIED_SOURCES += [
|
|||
'threading/Mutex.cpp',
|
||||
'threading/ProtectedData.cpp',
|
||||
'util/AllocPolicy.cpp',
|
||||
'util/CompleteFile.cpp',
|
||||
'util/NativeStack.cpp',
|
||||
'util/Printf.cpp',
|
||||
'util/StringBuffer.cpp',
|
||||
|
@ -368,6 +369,7 @@ UNIFIED_SOURCES += [
|
|||
'vm/CharacterEncoding.cpp',
|
||||
'vm/CodeCoverage.cpp',
|
||||
'vm/Compartment.cpp',
|
||||
'vm/CompilationAndEvaluation.cpp',
|
||||
'vm/Compression.cpp',
|
||||
'vm/DateTime.cpp',
|
||||
'vm/Debugger.cpp',
|
||||
|
@ -393,6 +395,7 @@ UNIFIED_SOURCES += [
|
|||
'vm/MemoryMetrics.cpp',
|
||||
'vm/NativeObject.cpp',
|
||||
'vm/ObjectGroup.cpp',
|
||||
'vm/OffThreadScriptCompilation.cpp',
|
||||
'vm/PIC.cpp',
|
||||
'vm/Printer.cpp',
|
||||
'vm/Probes.cpp',
|
||||
|
|
|
@ -877,7 +877,7 @@ RunFile(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
|
|||
.setIsRunOnce(true)
|
||||
.setNoScriptRval(true);
|
||||
|
||||
if (!JS::Compile(cx, options, file, &script)) {
|
||||
if (!JS::CompileUtf8File(cx, options, file, &script)) {
|
||||
return false;
|
||||
}
|
||||
MOZ_ASSERT(script);
|
||||
|
@ -1634,7 +1634,7 @@ LoadScript(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative)
|
|||
.setNoScriptRval(true);
|
||||
RootedScript script(cx);
|
||||
RootedValue unused(cx);
|
||||
if ((compileOnly && !Compile(cx, opts, filename.get(), &script)) ||
|
||||
if ((compileOnly && !CompileUtf8Path(cx, opts, filename.get(), &script)) ||
|
||||
!Evaluate(cx, opts, filename.get(), &unused))
|
||||
{
|
||||
return false;
|
||||
|
@ -3375,7 +3375,7 @@ DisassFile(JSContext* cx, unsigned argc, Value* vp)
|
|||
.setIsRunOnce(true)
|
||||
.setNoScriptRval(true);
|
||||
|
||||
if (!JS::Compile(cx, options, filename.get(), &script)) {
|
||||
if (!JS::CompileUtf8Path(cx, options, filename.get(), &script)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "util/CompleteFile.h"
|
||||
|
||||
#include <cstring> // std::strcmp
|
||||
#include <stdio.h> // FILE, fileno, fopen, getc, getc_unlocked, _getc_nolock
|
||||
#include <sys/stat.h> // stat, fstat
|
||||
|
||||
#include "jsapi.h" // JS_ReportErrorNumberLatin1
|
||||
#include "jsfriendapi.h" // js::GetErrorMessage, JSMSG_CANT_OPEN
|
||||
|
||||
bool
|
||||
js::ReadCompleteFile(JSContext* cx, FILE* fp, FileContents& buffer)
|
||||
{
|
||||
/* Get the complete length of the file, if possible. */
|
||||
struct stat st;
|
||||
int ok = fstat(fileno(fp), &st);
|
||||
if (ok != 0) {
|
||||
return false;
|
||||
}
|
||||
if (st.st_size > 0) {
|
||||
if (!buffer.reserve(st.st_size)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use the fastest available getc. */
|
||||
auto fast_getc =
|
||||
#if defined(HAVE_GETC_UNLOCKED)
|
||||
getc_unlocked
|
||||
#elif defined(HAVE__GETC_NOLOCK)
|
||||
_getc_nolock
|
||||
#else
|
||||
getc
|
||||
#endif
|
||||
;
|
||||
|
||||
// Read in the whole file. Note that we can't assume the data's length
|
||||
// is actually st.st_size, because 1) some files lie about their size
|
||||
// (/dev/zero and /dev/random), and 2) reading files in text mode on
|
||||
// Windows collapses "\r\n" pairs to single \n characters.
|
||||
for (;;) {
|
||||
int c = fast_getc(fp);
|
||||
if (c == EOF) {
|
||||
break;
|
||||
}
|
||||
if (!buffer.append(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a source file for reading. Supports "-" and nullptr to mean stdin. The
|
||||
* return value must be fclosed unless it is stdin.
|
||||
*/
|
||||
bool
|
||||
js::AutoFile::open(JSContext* cx, const char* filename)
|
||||
{
|
||||
if (!filename || std::strcmp(filename, "-") == 0) {
|
||||
fp_ = stdin;
|
||||
} else {
|
||||
fp_ = fopen(filename, "r");
|
||||
if (!fp_) {
|
||||
/*
|
||||
* Use Latin1 variant here because the encoding of filename is
|
||||
* platform dependent.
|
||||
*/
|
||||
JS_ReportErrorNumberLatin1(cx, GetErrorMessage, nullptr, JSMSG_CANT_OPEN,
|
||||
filename, "No such file or directory");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef util_CompleteFile_h
|
||||
#define util_CompleteFile_h
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
|
||||
#include <stdint.h> // uint8_t
|
||||
#include <stdio.h> // fclose, FILE, stdin
|
||||
|
||||
#include "js/AllocPolicy.h" // js::TempAllocPolicy
|
||||
#include "js/Vector.h" // js::Vector
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace js {
|
||||
|
||||
using FileContents = Vector<uint8_t, 8, TempAllocPolicy>;
|
||||
|
||||
extern bool
|
||||
ReadCompleteFile(JSContext* cx, FILE* fp, FileContents& buffer);
|
||||
|
||||
class AutoFile
|
||||
{
|
||||
FILE* fp_ = nullptr;
|
||||
|
||||
public:
|
||||
AutoFile() {}
|
||||
|
||||
~AutoFile()
|
||||
{
|
||||
if (fp_ && fp_ != stdin) {
|
||||
fclose(fp_);
|
||||
}
|
||||
}
|
||||
|
||||
FILE* fp() const { return fp_; }
|
||||
|
||||
bool open(JSContext* cx, const char* filename);
|
||||
|
||||
bool readAll(JSContext* cx, FileContents& buffer)
|
||||
{
|
||||
MOZ_ASSERT(fp_);
|
||||
return ReadCompleteFile(cx, fp_, buffer);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
#endif /* util_CompleteFile_h */
|
|
@ -0,0 +1,618 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Same-thread compilation and evaluation APIs. */
|
||||
|
||||
#include "js/CompilationAndEvaluation.h"
|
||||
|
||||
#include "mozilla/Maybe.h" // mozilla::None, mozilla::Some
|
||||
#include "mozilla/TextUtils.h" // mozilla::IsAscii
|
||||
|
||||
#include <algorithm> // std::all_of
|
||||
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
#include "frontend/FullParseHandler.h" // frontend::FullParseHandler
|
||||
#include "frontend/ParseContext.h" // frontend::UsedNameTracker
|
||||
#include "frontend/Parser.h" // frontend::Parser, frontend::ParseGoal
|
||||
#include "js/CharacterEncoding.h" // JS::UTF8CharsToNewTwoByteCharsZ
|
||||
#include "js/RootingAPI.h" // JS::Rooted
|
||||
#include "js/SourceBufferHolder.h" // JS::SourceBufferHolder
|
||||
#include "js/TypeDecls.h" // JS::HandleObject, JS::MutableHandleScript
|
||||
#include "util/CompleteFile.h" // js::FileContents, js::ReadCompleteFile
|
||||
#include "util/StringBuffer.h" // js::StringBuffer
|
||||
#include "vm/Debugger.h" // js::Debugger
|
||||
#include "vm/EnvironmentObject.h" // js::CreateNonSyntacticEnvironmentChain
|
||||
#include "vm/Interpreter.h" // js::Execute
|
||||
#include "vm/JSContext.h" // JSContext
|
||||
|
||||
#include "vm/JSContext-inl.h" // JSContext::check
|
||||
|
||||
using JS::CompileOptions;
|
||||
using JS::HandleObject;
|
||||
using JS::ReadOnlyCompileOptions;
|
||||
using JS::SourceBufferHolder;
|
||||
|
||||
using namespace js;
|
||||
|
||||
static bool
|
||||
CompileSourceBuffer(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
|
||||
{
|
||||
ScopeKind scopeKind = options.nonSyntacticScope ? ScopeKind::NonSyntactic : ScopeKind::Global;
|
||||
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
|
||||
script.set(frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(), scopeKind, options, srcBuf));
|
||||
return !!script;
|
||||
}
|
||||
|
||||
static bool
|
||||
CompileLatin1(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, JS::MutableHandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(!options.utf8);
|
||||
|
||||
char16_t* chars = InflateString(cx, bytes, length);
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
|
||||
return CompileSourceBuffer(cx, options, source, script);
|
||||
}
|
||||
|
||||
static bool
|
||||
CompileUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, JS::MutableHandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(options.utf8);
|
||||
|
||||
char16_t* chars = JS::UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
|
||||
return CompileSourceBuffer(cx, options, source, script);
|
||||
}
|
||||
|
||||
static bool
|
||||
CompileFile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
FILE* fp, JS::MutableHandleScript script)
|
||||
{
|
||||
FileContents buffer(cx);
|
||||
if (!ReadCompleteFile(cx, fp, buffer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return options.utf8
|
||||
? ::CompileUtf8(cx, options,
|
||||
reinterpret_cast<const char*>(buffer.begin()), buffer.length(), script)
|
||||
: ::CompileLatin1(cx, options,
|
||||
reinterpret_cast<const char*>(buffer.begin()), buffer.length(),
|
||||
script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::Compile(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
|
||||
{
|
||||
return CompileSourceBuffer(cx, options, srcBuf, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileLatin1(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, JS::MutableHandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(!options.utf8);
|
||||
return ::CompileLatin1(cx, options, bytes, length, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileUtf8(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, JS::MutableHandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(options.utf8);
|
||||
return ::CompileUtf8(cx, options, bytes, length, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileUtf8File(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
FILE* file, JS::MutableHandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(options.utf8,
|
||||
"options.utf8 must be set when JS::CompileUtf8File is called");
|
||||
return CompileFile(cx, options, file, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileUtf8Path(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* filename, JS::MutableHandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(optionsArg.utf8,
|
||||
"this function only compiles UTF-8 source text in the file at "
|
||||
"the given path");
|
||||
|
||||
AutoFile file;
|
||||
if (!file.open(cx, filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setFileAndLine(filename, 1);
|
||||
return CompileUtf8File(cx, options, file.fp(), script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, JS::MutableHandleScript script)
|
||||
{
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setNonSyntacticScope(true);
|
||||
return CompileSourceBuffer(cx, options, srcBuf, script);
|
||||
}
|
||||
|
||||
bool
|
||||
JS::CompileLatin1ForNonSyntacticScope(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* bytes, size_t length,
|
||||
JS::MutableHandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(!optionsArg.utf8,
|
||||
"this function only compiles Latin-1 source text");
|
||||
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setNonSyntacticScope(true);
|
||||
return ::CompileLatin1(cx, options, bytes, length, script);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_CompileScript(JSContext* cx, const char* bytes, size_t length,
|
||||
const JS::CompileOptions& options, MutableHandleScript script)
|
||||
{
|
||||
return options.utf8
|
||||
? ::CompileUtf8(cx, options, bytes, length, script)
|
||||
: ::CompileLatin1(cx, options, bytes, length, script);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_CompileUCScript(JSContext* cx, JS::SourceBufferHolder& srcBuf,
|
||||
const JS::CompileOptions& options, MutableHandleScript script)
|
||||
{
|
||||
return CompileSourceBuffer(cx, options, srcBuf, script);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_BufferIsCompilableUnit(JSContext* cx, HandleObject obj, const char* utf8, size_t length)
|
||||
{
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(obj);
|
||||
|
||||
cx->clearPendingException();
|
||||
|
||||
JS::UniqueTwoByteChars chars
|
||||
{ JS::UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(utf8, length), &length).get() };
|
||||
if (!chars) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Return true on any out-of-memory error or non-EOF-related syntax error, so our
|
||||
// caller doesn't try to collect more buffered source.
|
||||
bool result = true;
|
||||
|
||||
using frontend::UsedNameTracker;
|
||||
using frontend::CreateScriptSourceObject;
|
||||
using frontend::Parser;
|
||||
using frontend::FullParseHandler;
|
||||
using frontend::ParseGoal;
|
||||
|
||||
CompileOptions options(cx);
|
||||
UsedNameTracker usedNames(cx);
|
||||
|
||||
Rooted<ScriptSourceObject*> sourceObject(cx);
|
||||
sourceObject = CreateScriptSourceObject(cx, options, mozilla::Nothing());
|
||||
if (!sourceObject) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Parser<FullParseHandler, char16_t> parser(cx, cx->tempLifoAlloc(), options,
|
||||
chars.get(), length, /* foldConstants = */ true,
|
||||
usedNames, nullptr, nullptr, sourceObject,
|
||||
ParseGoal::Script);
|
||||
JS::WarningReporter older = JS::SetWarningReporter(cx, nullptr);
|
||||
if (!parser.checkOptions() || !parser.parse()) {
|
||||
// We ran into an error. If it was because we ran out of source, we
|
||||
// return false so our caller knows to try to collect more buffered
|
||||
// source.
|
||||
if (parser.isUnexpectedEOF()) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
cx->clearPendingException();
|
||||
}
|
||||
JS::SetWarningReporter(cx, older);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* enclosingScope is a scope, if any (e.g. a WithScope). If the scope is the
|
||||
* global scope, this must be null.
|
||||
*
|
||||
* enclosingEnv is an environment to use, if it's not the global.
|
||||
*/
|
||||
static bool
|
||||
CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
HandleAtom name, bool isInvalidName,
|
||||
SourceBufferHolder& srcBuf, uint32_t parameterListEnd,
|
||||
HandleObject enclosingEnv, HandleScope enclosingScope,
|
||||
MutableHandleFunction fun)
|
||||
{
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(enclosingEnv);
|
||||
RootedAtom funAtom(cx);
|
||||
|
||||
fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL,
|
||||
isInvalidName ? nullptr : name,
|
||||
/* proto = */ nullptr,
|
||||
gc::AllocKind::FUNCTION, TenuredObject,
|
||||
enclosingEnv));
|
||||
if (!fun) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the static scope chain matches up when we have a
|
||||
// non-syntactic scope.
|
||||
MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(enclosingEnv),
|
||||
enclosingScope->hasOnChain(ScopeKind::NonSyntactic));
|
||||
|
||||
if (!js::frontend::CompileStandaloneFunction(cx, fun, optionsArg, srcBuf,
|
||||
mozilla::Some(parameterListEnd), enclosingScope))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// When function name is not valid identifier, generated function source
|
||||
// in srcBuf doesn't have function name. Set it here.
|
||||
if (isInvalidName) {
|
||||
fun->setAtom(name);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
BuildFunctionString(const char* name, size_t nameLen,
|
||||
unsigned nargs, const char* const* argnames,
|
||||
const SourceBufferHolder& srcBuf, StringBuffer* out,
|
||||
uint32_t* parameterListEnd)
|
||||
{
|
||||
MOZ_ASSERT(out);
|
||||
MOZ_ASSERT(parameterListEnd);
|
||||
|
||||
if (!out->ensureTwoByteChars()) {
|
||||
return false;
|
||||
}
|
||||
if (!out->append("function ")) {
|
||||
return false;
|
||||
}
|
||||
if (name) {
|
||||
if (!out->append(name, nameLen)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!out->append("(")) {
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = 0; i < nargs; i++) {
|
||||
if (i != 0) {
|
||||
if (!out->append(", ")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!out->append(argnames[i], strlen(argnames[i]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Remember the position of ")".
|
||||
*parameterListEnd = out->length();
|
||||
MOZ_ASSERT(FunctionConstructorMedialSigils[0] == ')');
|
||||
|
||||
if (!out->append(FunctionConstructorMedialSigils)) {
|
||||
return false;
|
||||
}
|
||||
if (!out->append(srcBuf.get(), srcBuf.length())) {
|
||||
return false;
|
||||
}
|
||||
if (!out->append(FunctionConstructorFinalBrace)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
const char* name, unsigned nargs, const char* const* argnames,
|
||||
SourceBufferHolder& srcBuf, MutableHandleFunction fun)
|
||||
{
|
||||
RootedObject env(cx);
|
||||
RootedScope scope(cx);
|
||||
if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t nameLen = 0;
|
||||
bool isInvalidName = false;
|
||||
RootedAtom nameAtom(cx);
|
||||
if (name) {
|
||||
nameLen = strlen(name);
|
||||
nameAtom = Atomize(cx, name, nameLen);
|
||||
if (!nameAtom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If name is not valid identifier
|
||||
if (!js::frontend::IsIdentifier(name, nameLen)) {
|
||||
isInvalidName = true;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t parameterListEnd;
|
||||
StringBuffer funStr(cx);
|
||||
if (!BuildFunctionString(isInvalidName ? nullptr : name, nameLen, nargs, argnames, srcBuf,
|
||||
&funStr, ¶meterListEnd))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t newLen = funStr.length();
|
||||
SourceBufferHolder newSrcBuf(funStr.stealChars(), newLen, SourceBufferHolder::GiveOwnership);
|
||||
|
||||
return CompileFunction(cx, options, nameAtom, isInvalidName, newSrcBuf, parameterListEnd, env,
|
||||
scope, fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
|
||||
const ReadOnlyCompileOptions& options,
|
||||
const char* name, unsigned nargs, const char* const* argnames,
|
||||
const char* bytes, size_t length, MutableHandleFunction fun)
|
||||
{
|
||||
char16_t* chars;
|
||||
if (options.utf8) {
|
||||
chars = UTF8CharsToNewTwoByteCharsZ(cx, UTF8Chars(bytes, length), &length).get();
|
||||
} else {
|
||||
chars = InflateString(cx, bytes, length);
|
||||
}
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceBufferHolder source(chars, length, SourceBufferHolder::GiveOwnership);
|
||||
return CompileFunction(cx, envChain, options, name, nargs, argnames,
|
||||
source, fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::InitScriptSourceElement(JSContext* cx, HandleScript script,
|
||||
HandleObject element, HandleString elementAttrName)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
|
||||
RootedScriptSourceObject sso(cx, &script->sourceObject()->as<ScriptSourceObject>());
|
||||
return ScriptSourceObject::initElementProperties(cx, sso, element, elementAttrName);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::ExposeScriptToDebugger(JSContext* cx, HandleScript script)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
|
||||
MOZ_ASSERT(script->hideScriptFromDebugger());
|
||||
script->clearHideScriptFromDebugger();
|
||||
Debugger::onNewScript(cx, script);
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE static bool
|
||||
ExecuteScript(JSContext* cx, HandleObject scope, HandleScript script, Value* rval)
|
||||
{
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(scope, script);
|
||||
MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(scope), script->hasNonSyntacticScope());
|
||||
return Execute(cx, script, *scope, rval);
|
||||
}
|
||||
|
||||
static bool
|
||||
ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg, Value* rval)
|
||||
{
|
||||
RootedObject env(cx);
|
||||
RootedScope dummy(cx);
|
||||
if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &dummy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedScript script(cx, scriptArg);
|
||||
if (!script->hasNonSyntacticScope() && !IsGlobalLexicalEnvironment(env)) {
|
||||
script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
js::Debugger::onNewScript(cx, script);
|
||||
}
|
||||
|
||||
return ExecuteScript(cx, env, script, rval);
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||
JS_ExecuteScript(JSContext* cx, HandleScript scriptArg, MutableHandleValue rval)
|
||||
{
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
return ExecuteScript(cx, globalLexical, scriptArg, rval.address());
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||
JS_ExecuteScript(JSContext* cx, HandleScript scriptArg)
|
||||
{
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
return ExecuteScript(cx, globalLexical, scriptArg, nullptr);
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||
JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain,
|
||||
HandleScript scriptArg, MutableHandleValue rval)
|
||||
{
|
||||
return ExecuteScript(cx, envChain, scriptArg, rval.address());
|
||||
}
|
||||
|
||||
MOZ_NEVER_INLINE JS_PUBLIC_API(bool)
|
||||
JS_ExecuteScript(JSContext* cx, AutoObjectVector& envChain, HandleScript scriptArg)
|
||||
{
|
||||
return ExecuteScript(cx, envChain, scriptArg, nullptr);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CloneAndExecuteScript(JSContext* cx, HandleScript scriptArg,
|
||||
JS::MutableHandleValue rval)
|
||||
{
|
||||
CHECK_THREAD(cx);
|
||||
RootedScript script(cx, scriptArg);
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
if (script->realm() != cx->realm()) {
|
||||
script = CloneGlobalScript(cx, ScopeKind::Global, script);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
||||
js::Debugger::onNewScript(cx, script);
|
||||
}
|
||||
return ExecuteScript(cx, globalLexical, script, rval.address());
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CloneAndExecuteScript(JSContext* cx, JS::AutoObjectVector& envChain,
|
||||
HandleScript scriptArg,
|
||||
JS::MutableHandleValue rval)
|
||||
{
|
||||
CHECK_THREAD(cx);
|
||||
RootedScript script(cx, scriptArg);
|
||||
if (script->realm() != cx->realm()) {
|
||||
script = CloneGlobalScript(cx, ScopeKind::NonSyntactic, script);
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
||||
js::Debugger::onNewScript(cx, script);
|
||||
}
|
||||
return ExecuteScript(cx, envChain, script, rval.address());
|
||||
}
|
||||
|
||||
static bool
|
||||
Evaluate(JSContext* cx, ScopeKind scopeKind, HandleObject env,
|
||||
const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||
{
|
||||
CompileOptions options(cx, optionsArg);
|
||||
MOZ_ASSERT(!cx->zone()->isAtomsZone());
|
||||
AssertHeapIsIdle();
|
||||
CHECK_THREAD(cx);
|
||||
cx->check(env);
|
||||
MOZ_ASSERT_IF(!IsGlobalLexicalEnvironment(env), scopeKind == ScopeKind::NonSyntactic);
|
||||
|
||||
options.setIsRunOnce(true);
|
||||
RootedScript script(cx, frontend::CompileGlobalScript(cx, cx->tempLifoAlloc(),
|
||||
scopeKind, options, srcBuf));
|
||||
if (!script) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool result = Execute(cx, script, *env,
|
||||
options.noScriptRval ? nullptr : rval.address());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool
|
||||
Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||
{
|
||||
RootedObject env(cx);
|
||||
RootedScope scope(cx);
|
||||
if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope)) {
|
||||
return false;
|
||||
}
|
||||
return ::Evaluate(cx, scope->kind(), env, optionsArg, srcBuf, rval);
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(bool)
|
||||
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const char* bytes, size_t length, MutableHandleValue rval)
|
||||
{
|
||||
char16_t* chars;
|
||||
if (options.utf8) {
|
||||
chars = UTF8CharsToNewTwoByteCharsZ(cx, JS::UTF8Chars(bytes, length), &length).get();
|
||||
} else {
|
||||
chars = InflateString(cx, bytes, length);
|
||||
}
|
||||
if (!chars) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SourceBufferHolder srcBuf(chars, length, SourceBufferHolder::GiveOwnership);
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
bool ok = ::Evaluate(cx, ScopeKind::Global, globalLexical, options, srcBuf, rval);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static bool
|
||||
Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* filename, MutableHandleValue rval)
|
||||
{
|
||||
FileContents buffer(cx);
|
||||
{
|
||||
AutoFile file;
|
||||
if (!file.open(cx, filename) || !file.readAll(cx, buffer)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CompileOptions options(cx, optionsArg);
|
||||
options.setFileAndLine(filename, 1);
|
||||
return Evaluate(cx, options, reinterpret_cast<const char*>(buffer.begin()), buffer.length(), rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||
{
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
return ::Evaluate(cx, ScopeKind::Global, globalLexical, optionsArg, srcBuf, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::Evaluate(JSContext* cx, AutoObjectVector& envChain, const ReadOnlyCompileOptions& optionsArg,
|
||||
SourceBufferHolder& srcBuf, MutableHandleValue rval)
|
||||
{
|
||||
return ::Evaluate(cx, envChain, optionsArg, srcBuf, rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::Evaluate(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* filename, MutableHandleValue rval)
|
||||
{
|
||||
return ::Evaluate(cx, optionsArg, filename, rval);
|
||||
}
|
|
@ -922,6 +922,51 @@ const Class NonSyntacticVariablesObject::class_ = {
|
|||
JSCLASS_IS_ANONYMOUS
|
||||
};
|
||||
|
||||
bool
|
||||
js::CreateNonSyntacticEnvironmentChain(JSContext* cx, AutoObjectVector& envChain,
|
||||
MutableHandleObject env, MutableHandleScope scope)
|
||||
{
|
||||
RootedObject globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||
if (!CreateObjectsForEnvironmentChain(cx, envChain, globalLexical, env)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!envChain.empty()) {
|
||||
scope.set(GlobalScope::createEmpty(cx, ScopeKind::NonSyntactic));
|
||||
if (!scope) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The XPConnect subscript loader, which may pass in its own
|
||||
// environments to load scripts in, expects the environment chain to
|
||||
// be the holder of "var" declarations. In SpiderMonkey, such objects
|
||||
// are called "qualified varobjs", the "qualified" part meaning the
|
||||
// declaration was qualified by "var". There is only sadness.
|
||||
//
|
||||
// See JSObject::isQualifiedVarObj.
|
||||
if (!JSObject::setQualifiedVarObj(cx, env)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Also get a non-syntactic lexical environment to capture 'let' and
|
||||
// 'const' bindings. To persist lexical bindings, we have a 1-1
|
||||
// mapping with the final unwrapped environment object (the
|
||||
// environment that stores the 'var' bindings) and the lexical
|
||||
// environment.
|
||||
//
|
||||
// TODOshu: disallow the subscript loader from using non-distinguished
|
||||
// objects as dynamic scopes.
|
||||
env.set(ObjectRealm::get(env).getOrCreateNonSyntacticLexicalEnvironment(cx, env));
|
||||
if (!env) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
scope.set(&cx->global()->emptyGlobalScope());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* static */ LexicalEnvironmentObject*
|
||||
|
@ -3810,7 +3855,6 @@ js::GetFrameEnvironmentAndScope(JSContext* cx, AbstractFramePtr frame, jsbytecod
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
typedef HashSet<PropertyName*> PropertyNameSet;
|
||||
|
|
|
@ -612,6 +612,10 @@ class NonSyntacticVariablesObject : public EnvironmentObject
|
|||
static NonSyntacticVariablesObject* create(JSContext* cx);
|
||||
};
|
||||
|
||||
extern bool
|
||||
CreateNonSyntacticEnvironmentChain(JSContext* cx, JS::AutoObjectVector& envChain,
|
||||
MutableHandleObject env, MutableHandleScope scope);
|
||||
|
||||
// With environment objects on the run-time environment chain.
|
||||
class WithEnvironmentObject : public EnvironmentObject
|
||||
{
|
||||
|
|
|
@ -0,0 +1,209 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "js/OffThreadScriptCompilation.h"
|
||||
|
||||
#include "mozilla/Assertions.h" // MOZ_ASSERT
|
||||
#include "mozilla/Range.h" // mozilla::Range
|
||||
#include "mozilla/Vector.h" // mozilla::Vector
|
||||
|
||||
#include <stddef.h> // size_t
|
||||
|
||||
#include "jspubtd.h" // js::CurrentThreadCanAccessRuntime
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions
|
||||
#include "vm/HelperThreads.h" // js::OffThreadParsingMustWaitForGC, js::StartOffThreadParseScript
|
||||
#include "vm/JSContext.h" // JSContext
|
||||
#include "vm/Runtime.h" // js::CanUseExtraThreads
|
||||
|
||||
using namespace js;
|
||||
|
||||
using JS::ReadOnlyCompileOptions;
|
||||
|
||||
enum class OffThread
|
||||
{
|
||||
Compile, Decode, DecodeBinAST
|
||||
};
|
||||
|
||||
static bool
|
||||
CanDoOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length, OffThread what)
|
||||
{
|
||||
static const size_t TINY_LENGTH = 5 * 1000;
|
||||
static const size_t HUGE_SRC_LENGTH = 100 * 1000;
|
||||
static const size_t HUGE_BC_LENGTH = 367 * 1000;
|
||||
static const size_t HUGE_BINAST_LENGTH = 70 * 1000;
|
||||
|
||||
// TODO: We can't decode BinAST off main thread until bug 1459555 is fixed.
|
||||
if (what == OffThread::DecodeBinAST) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// These are heuristics which the caller may choose to ignore (e.g., for
|
||||
// testing purposes).
|
||||
if (!options.forceAsync) {
|
||||
// Compiling off the main thread inolves creating a new Zone and other
|
||||
// significant overheads. Don't bother if the script is tiny.
|
||||
if (length < TINY_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the parsing task would have to wait for GC to complete, it'll probably
|
||||
// be faster to just start it synchronously on the main thread unless the
|
||||
// script is huge.
|
||||
if (OffThreadParsingMustWaitForGC(cx->runtime())) {
|
||||
if (what == OffThread::Compile && length < HUGE_SRC_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
if (what == OffThread::Decode && length < HUGE_BC_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
if (what == OffThread::DecodeBinAST && length < HUGE_BINAST_LENGTH) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cx->runtime()->canUseParallelParsing() &&
|
||||
CanUseExtraThreads() &&
|
||||
!mozilla::recordreplay::IsRecordingOrReplaying();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CanCompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
|
||||
{
|
||||
return CanDoOffThread(cx, options, length, OffThread::Compile);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CanDecodeOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
|
||||
{
|
||||
return CanDoOffThread(cx, options, length, OffThread::Decode);
|
||||
}
|
||||
|
||||
#ifdef JS_BUILD_BINAST
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CanDecodeBinASTOffThread(JSContext* cx, const ReadOnlyCompileOptions& options, size_t length)
|
||||
{
|
||||
return CanDoOffThread(cx, options, length, OffThread::DecodeBinAST);
|
||||
}
|
||||
#endif
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileOffThread(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
MOZ_ASSERT(CanCompileOffThread(cx, options, srcBuf.length()));
|
||||
return StartOffThreadParseScript(cx, options, srcBuf, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript*)
|
||||
JS::FinishOffThreadScript(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishScriptParseTask(cx, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelOffThreadScript(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::Script, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::CompileOffThreadModule(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
JS::SourceBufferHolder& srcBuf,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
MOZ_ASSERT(CanCompileOffThread(cx, options, srcBuf.length()));
|
||||
return StartOffThreadParseModule(cx, options, srcBuf, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript*)
|
||||
JS::FinishOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishModuleParseTask(cx, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelOffThreadModule(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::Module, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
mozilla::Vector<uint8_t>& buffer /* TranscodeBuffer& */, size_t cursor,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
JS::TranscodeRange range(buffer.begin() + cursor, buffer.length() - cursor);
|
||||
MOZ_ASSERT(CanDecodeOffThread(cx, options, range.length()));
|
||||
return StartOffThreadDecodeScript(cx, options, range, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::DecodeOffThreadScript(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
const mozilla::Range<uint8_t>& range /* TranscodeRange& */,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
MOZ_ASSERT(CanDecodeOffThread(cx, options, range.length()));
|
||||
return StartOffThreadDecodeScript(cx, options, range, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::DecodeMultiOffThreadScripts(JSContext* cx, const ReadOnlyCompileOptions& options,
|
||||
TranscodeSources& sources,
|
||||
OffThreadCompileCallback callback, void* callbackData)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
size_t length = 0;
|
||||
for (auto& source : sources) {
|
||||
length += source.range.length();
|
||||
}
|
||||
MOZ_ASSERT(CanCompileOffThread(cx, options, length));
|
||||
#endif
|
||||
return StartOffThreadDecodeMultiScripts(cx, options, sources, callback, callbackData);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript*)
|
||||
JS::FinishOffThreadScriptDecoder(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishScriptDecodeTask(cx, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelOffThreadScriptDecoder(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::ScriptDecode, token);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS::FinishMultiOffThreadScriptsDecoder(JSContext* cx, JS::OffThreadToken* token, MutableHandle<ScriptVector> scripts)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
return HelperThreadState().finishMultiScriptsDecodeTask(cx, token, scripts);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::CancelMultiOffThreadScriptsDecoder(JSContext* cx, JS::OffThreadToken* token)
|
||||
{
|
||||
MOZ_ASSERT(cx);
|
||||
MOZ_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
|
||||
HelperThreadState().cancelParseTask(cx->runtime(), ParseTaskKind::MultiScriptsDecode, token);
|
||||
}
|
|
@ -879,18 +879,18 @@ mozJSComponentLoader::ObjectForLocation(ComponentLoaderInfo& aInfo,
|
|||
// don't early return for them here.
|
||||
auto buf = map.get<char>();
|
||||
if (reuseGlobal) {
|
||||
CompileForNonSyntacticScope(cx, options, buf.get(), map.size(), &script);
|
||||
CompileLatin1ForNonSyntacticScope(cx, options, buf.get(), map.size(), &script);
|
||||
} else {
|
||||
Compile(cx, options, buf.get(), map.size(), &script);
|
||||
CompileLatin1(cx, options, buf.get(), map.size(), &script);
|
||||
}
|
||||
} else {
|
||||
nsCString str;
|
||||
MOZ_TRY_VAR(str, ReadScript(aInfo));
|
||||
|
||||
if (reuseGlobal) {
|
||||
CompileForNonSyntacticScope(cx, options, str.get(), str.Length(), &script);
|
||||
CompileLatin1ForNonSyntacticScope(cx, options, str.get(), str.Length(), &script);
|
||||
} else {
|
||||
Compile(cx, options, str.get(), str.Length(), &script);
|
||||
CompileLatin1(cx, options, str.get(), str.Length(), &script);
|
||||
}
|
||||
}
|
||||
// Propagate the exception, if one exists. Also, don't leave the stale
|
||||
|
|
|
@ -178,9 +178,9 @@ PrepareScript(nsIURI* uri,
|
|||
// the lazy source loader doesn't know the encoding.
|
||||
options.setSourceIsLazy(true);
|
||||
if (wantGlobalScript) {
|
||||
return JS::Compile(cx, options, buf, len, script);
|
||||
return JS::CompileLatin1(cx, options, buf, len, script);
|
||||
}
|
||||
return JS::CompileForNonSyntacticScope(cx, options, buf, len, script);
|
||||
return JS::CompileLatin1ForNonSyntacticScope(cx, options, buf, len, script);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -386,7 +386,7 @@ Load(JSContext* cx, unsigned argc, Value* vp)
|
|||
.setIsRunOnce(true);
|
||||
JS::Rooted<JSScript*> script(cx);
|
||||
JS::Rooted<JSObject*> global(cx, JS::CurrentGlobalOrNull(cx));
|
||||
JS::Compile(cx, options, file, &script);
|
||||
JS::CompileUtf8File(cx, options, file, &script);
|
||||
fclose(file);
|
||||
if (!script) {
|
||||
return false;
|
||||
|
@ -799,7 +799,7 @@ ProcessFile(AutoJSAPI& jsapi, const char* filename, FILE* file, bool forceTTY)
|
|||
.setFileAndLine(filename, 1)
|
||||
.setIsRunOnce(true)
|
||||
.setNoScriptRval(true);
|
||||
if (!JS::Compile(cx, options, file, &script)) {
|
||||
if (!JS::CompileUtf8File(cx, options, file, &script)) {
|
||||
return false;
|
||||
}
|
||||
return compileOnly || JS_ExecuteScript(cx, script, &unused);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<html class="reftest-wait">
|
||||
<head>
|
||||
<style>
|
||||
*|HTML {
|
||||
-moz-column-width: calc(15px)
|
||||
}
|
||||
|
||||
*|HTML .class_1 {
|
||||
border-style: dotted;
|
||||
float: inline-end ! important
|
||||
}
|
||||
|
||||
* {
|
||||
block-size: calc(2px);
|
||||
}
|
||||
</style>
|
||||
<script noFuzz>
|
||||
function frameLoad() {
|
||||
setInterval(function() {
|
||||
document.documentElement.appendChild(o1)
|
||||
document.documentElement.appendChild(o2)
|
||||
}, 250)
|
||||
try { document.documentElement.appendChild(o4) } catch (e) {}
|
||||
try { xhr = new XMLHttpRequest() } catch (e) {}
|
||||
try { xhr.open('GET', 'data:text/html,1', false) } catch (e) {}
|
||||
try { xhr.send() } catch (e) {}
|
||||
try { document.documentElement.appendChild(o3) } catch (e) {}
|
||||
try { this.contentWindow.location.reload() } catch (e) {}
|
||||
}
|
||||
|
||||
function start() {
|
||||
o1 = document.createElement('del')
|
||||
o2 = document.createElement('track')
|
||||
o3 = document.createElement('video')
|
||||
o4 = document.createElement('video')
|
||||
o1.setAttribute('class', 'class_1')
|
||||
o2.setAttribute('class', 'class_1')
|
||||
o3.setAttribute('class', 'class_1')
|
||||
frame = document.createElement('iframe')
|
||||
frame.addEventListener('load', frameLoad)
|
||||
setTimeout(function(){
|
||||
document.documentElement.innerHTML="1";
|
||||
document.documentElement.removeAttribute("class");
|
||||
}, 1000);
|
||||
document.firstElementChild.appendChild(frame)
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', start)
|
||||
</script>
|
||||
<body></body>
|
||||
</head>
|
||||
</html>
|
|
@ -540,6 +540,7 @@ load 1466638.html
|
|||
load 1467688.html
|
||||
load 1467964.html
|
||||
load 1469354.html
|
||||
load 1472027.html
|
||||
pref(layout.accessiblecaret.enabled,true) load 1472020.html
|
||||
load 1472027.html
|
||||
load 1489149.html
|
||||
load 1490037.html
|
||||
|
|
|
@ -1369,11 +1369,14 @@ nsContainerFrame*
|
|||
nsLayoutUtils::LastContinuationWithChild(nsContainerFrame* aFrame)
|
||||
{
|
||||
MOZ_ASSERT(aFrame, "NULL frame pointer");
|
||||
nsIFrame* f = aFrame->LastContinuation();
|
||||
while (!f->PrincipalChildList().FirstChild() && f->GetPrevContinuation()) {
|
||||
f = f->GetPrevContinuation();
|
||||
for (auto f = aFrame->LastContinuation(); f; f = f->GetPrevContinuation()) {
|
||||
for (nsIFrame::ChildListIterator lists(f); !lists.IsDone(); lists.Next()) {
|
||||
if (MOZ_LIKELY(!lists.CurrentList().IsEmpty())) {
|
||||
return static_cast<nsContainerFrame*>(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
return static_cast<nsContainerFrame*>(f);
|
||||
return aFrame;
|
||||
}
|
||||
|
||||
//static
|
||||
|
|
|
@ -1634,7 +1634,7 @@ nsITheme*
|
|||
nsPresContext::GetTheme()
|
||||
{
|
||||
if (!sNoTheme && !mTheme) {
|
||||
mTheme = do_GetService("@mozilla.org/chrome/chrome-native-theme;1");
|
||||
mTheme = NS_NewNativeTheme();
|
||||
if (!mTheme)
|
||||
sNoTheme = true;
|
||||
}
|
||||
|
|
|
@ -63,15 +63,17 @@ nsBox::EndXULLayout(nsBoxLayoutState& aState)
|
|||
}
|
||||
|
||||
bool nsBox::gGotTheme = false;
|
||||
nsITheme* nsBox::gTheme = nullptr;
|
||||
StaticRefPtr<nsITheme> nsBox::gTheme;
|
||||
|
||||
nsBox::nsBox(ClassID aID)
|
||||
: nsIFrame(aID)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsBox);
|
||||
if (!gGotTheme) {
|
||||
gGotTheme = true;
|
||||
CallGetService("@mozilla.org/chrome/chrome-native-theme;1", &gTheme);
|
||||
gTheme = NS_NewNativeTheme();
|
||||
if (gTheme) {
|
||||
gGotTheme = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,7 +88,7 @@ nsBox::~nsBox()
|
|||
nsBox::Shutdown()
|
||||
{
|
||||
gGotTheme = false;
|
||||
NS_IF_RELEASE(gTheme);
|
||||
gTheme = nullptr;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#define nsBox_h___
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsIFrame.h"
|
||||
|
||||
class nsITheme;
|
||||
|
@ -79,7 +80,7 @@ protected:
|
|||
nsresult EndXULLayout(nsBoxLayoutState& aState);
|
||||
|
||||
static bool gGotTheme;
|
||||
static nsITheme* gTheme;
|
||||
static mozilla::StaticRefPtr<nsITheme> gTheme;
|
||||
|
||||
enum eMouseThrough {
|
||||
unset,
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "nsMenuBarListener.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIDOMXULLabelElement.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "nsITheme.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
|
@ -200,17 +199,9 @@ bool
|
|||
nsTextBoxFrame::UpdateAccesskey(WeakFrame& aWeakThis)
|
||||
{
|
||||
nsAutoString accesskey;
|
||||
nsCOMPtr<nsIDOMXULLabelElement> labelElement = do_QueryInterface(mContent);
|
||||
NS_ENSURE_TRUE(aWeakThis.IsAlive(), false);
|
||||
if (labelElement) {
|
||||
// Accesskey may be stored on control.
|
||||
labelElement->GetAccessKey(accesskey);
|
||||
NS_ENSURE_TRUE(aWeakThis.IsAlive(), false);
|
||||
} else {
|
||||
mContent->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::accesskey,
|
||||
accesskey);
|
||||
}
|
||||
mContent->AsElement()->GetAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::accesskey,
|
||||
accesskey);
|
||||
|
||||
if (!accesskey.Equals(mAccessKey)) {
|
||||
// Need to get clean mTitle.
|
||||
|
|
|
@ -205,7 +205,6 @@ nsresult
|
|||
nsStreamTransportService::Init()
|
||||
{
|
||||
mPool = new nsThreadPool();
|
||||
NS_ENSURE_STATE(mPool);
|
||||
|
||||
// Configure the pool
|
||||
mPool->SetName(NS_LITERAL_CSTRING("StreamTrans"));
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
</binding>
|
||||
|
||||
<binding id="text-label" extends="chrome://global/content/bindings/text.xml#text-base">
|
||||
<implementation implements="nsIDOMXULLabelElement">
|
||||
<implementation>
|
||||
<property name="accessKey">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
|
@ -56,7 +56,7 @@
|
|||
<content>
|
||||
<children/><html:span anonid="accessKeyParens"></html:span>
|
||||
</content>
|
||||
<implementation implements="nsIDOMXULLabelElement">
|
||||
<implementation>
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
this.formatAccessKey(true);
|
||||
|
@ -76,6 +76,10 @@
|
|||
}
|
||||
if (control) {
|
||||
control.labelElement = this;
|
||||
var controlAccessKey = control.getAttribute("accesskey");
|
||||
if (controlAccessKey) {
|
||||
this.setAttribute("accesskey", controlAccessKey);
|
||||
}
|
||||
}
|
||||
|
||||
var accessKey = this.accessKey;
|
||||
|
@ -234,14 +238,7 @@
|
|||
<property name="accessKey">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
var accessKey = null;
|
||||
var labeledEl = this.labeledControlElement;
|
||||
if (labeledEl) {
|
||||
accessKey = labeledEl.getAttribute("accesskey");
|
||||
}
|
||||
if (!accessKey) {
|
||||
accessKey = this.getAttribute("accesskey");
|
||||
}
|
||||
var accessKey = this.getAttribute("accesskey");
|
||||
return accessKey ? accessKey[0] : null;
|
||||
]]>
|
||||
</getter>
|
||||
|
@ -277,7 +274,6 @@
|
|||
]]>
|
||||
</setter>
|
||||
</property>
|
||||
|
||||
</implementation>
|
||||
|
||||
<handlers>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PuppetBidiKeyboard.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
using namespace mozilla::widget;
|
||||
|
||||
|
@ -49,3 +50,10 @@ PuppetBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
|
|||
*aResult = mHaveBidiKeyboards;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIBidiKeyboard>
|
||||
nsIWidget::CreateBidiKeyboardContentProcess()
|
||||
{
|
||||
return do_AddRef(new PuppetBidiKeyboard());
|
||||
}
|
||||
|
|
|
@ -313,3 +313,9 @@ nsNativeThemeAndroid::GetWidgetTransparency(nsIFrame* aFrame, WidgetType aWidget
|
|||
{
|
||||
return eUnknownTransparency;
|
||||
}
|
||||
|
||||
already_AddRefed<nsITheme>
|
||||
NS_NewNativeTheme()
|
||||
{
|
||||
return do_AddRef(new nsNativeThemeAndroid());
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "nsToolkitCompsCID.h"
|
||||
#include "AndroidAlerts.h"
|
||||
#include "nsNativeThemeAndroid.h"
|
||||
|
||||
#include "mozilla/widget/ScreenManager.h"
|
||||
|
||||
|
@ -56,29 +55,8 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(AndroidAlerts)
|
|||
}
|
||||
}
|
||||
|
||||
static nsresult
|
||||
nsNativeThemeAndroidConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aOuter) {
|
||||
rv = NS_ERROR_NO_AGGREGATION;
|
||||
return rv;
|
||||
}
|
||||
|
||||
*aResult = nullptr;
|
||||
nsNativeThemeAndroid* inst = new nsNativeThemeAndroid();
|
||||
NS_ADDREF(inst);
|
||||
rv = inst->QueryInterface(aIID, aResult);
|
||||
NS_RELEASE(inst);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_APPSHELL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_THEMERENDERER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_TRANSFERABLE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
|
||||
|
@ -96,7 +74,6 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||
{ &kNS_APPSHELL_CID, false, nullptr, nsAppShellConstructor },
|
||||
{ &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor,
|
||||
mozilla::Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_THEMERENDERER_CID, false, nullptr, nsNativeThemeAndroidConstructor },
|
||||
{ &kNS_IDLE_SERVICE_CID, false, nullptr, nsIdleServiceAndroidConstructor },
|
||||
{ &kNS_TRANSFERABLE_CID, false, nullptr, nsTransferableConstructor },
|
||||
{ &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor },
|
||||
|
@ -116,7 +93,6 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
|||
{ "@mozilla.org/widget/appshell/android;1", &kNS_APPSHELL_CID },
|
||||
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID,
|
||||
mozilla::Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
|
||||
{ "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
|
||||
{ "@mozilla.org/widget/transferable;1", &kNS_TRANSFERABLE_CID },
|
||||
{ "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID },
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "nsBidiKeyboard.h"
|
||||
#include "nsCocoaUtils.h"
|
||||
#include "TextInputHandler.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
// This must be the last include:
|
||||
#include "nsObjCExceptions.h"
|
||||
|
@ -40,3 +41,10 @@ NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
|
|||
// not implemented yet
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIBidiKeyboard>
|
||||
nsIWidget::CreateBidiKeyboardInner()
|
||||
{
|
||||
return do_AddRef(new nsBidiKeyboard());
|
||||
}
|
||||
|
|
|
@ -4971,3 +4971,9 @@ nsNativeThemeCocoa::GetWidgetTransparency(nsIFrame* aFrame, WidgetType aWidgetTy
|
|||
return eUnknownTransparency;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsITheme>
|
||||
NS_NewNativeTheme()
|
||||
{
|
||||
return do_AddRef(new nsNativeThemeCocoa());
|
||||
}
|
||||
|
|
|
@ -82,12 +82,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(OSXNotificationCenter, Init)
|
|||
#include "nsMenuBarX.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeMenuServiceX)
|
||||
|
||||
#include "nsBidiKeyboard.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
|
||||
|
||||
#include "nsNativeThemeCocoa.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsNativeThemeCocoa)
|
||||
|
||||
#include "nsMacDockSupport.h"
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacDockSupport)
|
||||
|
||||
|
@ -120,8 +114,6 @@ NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_BIDIKEYBOARD_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_THEMERENDERER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_DEVICE_CONTEXT_SPEC_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_PRINTSESSION_CID);
|
||||
|
@ -152,9 +144,6 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||
{ &kNS_CLIPBOARDHELPER_CID, false, NULL, nsClipboardHelperConstructor },
|
||||
{ &kNS_DRAGSERVICE_CID, false, NULL, nsDragServiceConstructor,
|
||||
mozilla::Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_BIDIKEYBOARD_CID, false, NULL, nsBidiKeyboardConstructor,
|
||||
mozilla::Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_THEMERENDERER_CID, false, NULL, nsNativeThemeCocoaConstructor },
|
||||
{ &kNS_SCREENMANAGER_CID, false, NULL, ScreenManagerConstructor,
|
||||
mozilla::Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_DEVICE_CONTEXT_SPEC_CID, false, NULL, nsDeviceContextSpecXConstructor },
|
||||
|
@ -188,9 +177,6 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
|||
{ "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
|
||||
{ "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID,
|
||||
mozilla::Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID,
|
||||
mozilla::Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
|
||||
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID,
|
||||
mozilla::Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/gfx/devicecontextspec;1", &kNS_DEVICE_CONTEXT_SPEC_CID },
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "prlink.h"
|
||||
|
||||
#include "nsBidiKeyboard.h"
|
||||
#include "nsIWidget.h"
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard)
|
||||
|
@ -53,3 +54,10 @@ NS_IMETHODIMP nsBidiKeyboard::GetHaveBidiKeyboards(bool* aResult)
|
|||
// not implemented yet
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIBidiKeyboard>
|
||||
nsIWidget::CreateBidiKeyboardInner()
|
||||
{
|
||||
return do_AddRef(new nsBidiKeyboard());
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsNativeThemeGTK.h"
|
||||
#include "HeadlessThemeGTK.h"
|
||||
#include "nsStyleConsts.h"
|
||||
#include "gtkdrawing.h"
|
||||
#include "ScreenHelperGTK.h"
|
||||
|
@ -65,6 +66,9 @@ NS_IMPL_ISUPPORTS_INHERITED(nsNativeThemeGTK, nsNativeTheme, nsITheme,
|
|||
|
||||
static int gLastGdkError;
|
||||
|
||||
// from nsWindow.cpp
|
||||
extern bool gDisableNativeTheme;
|
||||
|
||||
// Return scale factor of the monitor where the window is located
|
||||
// by the most part or layout.css.devPixelsPerPx pref if set to > 0.
|
||||
static inline gint
|
||||
|
@ -2143,3 +2147,20 @@ nsNativeThemeGTK::WidgetAppearanceDependsOnWindowFocus(StyleAppearance aWidgetTy
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
already_AddRefed<nsITheme>
|
||||
NS_NewNativeTheme()
|
||||
{
|
||||
nsCOMPtr<nsITheme> inst;
|
||||
|
||||
if (gDisableNativeTheme) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (gfxPlatform::IsHeadless()) {
|
||||
inst = new HeadlessThemeGTK();
|
||||
} else {
|
||||
inst = new nsNativeThemeGTK();
|
||||
}
|
||||
return inst.forget();
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "nsColorPicker.h"
|
||||
#include "nsFilePicker.h"
|
||||
#include "nsSound.h"
|
||||
#include "nsBidiKeyboard.h"
|
||||
#include "nsGTKToolkit.h"
|
||||
#include "WakeLockListener.h"
|
||||
|
||||
|
@ -49,9 +48,6 @@
|
|||
#include "GfxInfoX11.h"
|
||||
#endif
|
||||
|
||||
#include "nsNativeThemeGTK.h"
|
||||
#include "HeadlessThemeGTK.h"
|
||||
|
||||
#include "nsIComponentRegistrar.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
|
@ -62,7 +58,6 @@ using namespace mozilla;
|
|||
using namespace mozilla::widget;
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
|
||||
#ifdef MOZ_X11
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIdleServiceGTK, nsIdleServiceGTK::GetInstance)
|
||||
|
@ -74,39 +69,6 @@ NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRef
|
|||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsImageToPixbuf)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(TaskbarProgress)
|
||||
|
||||
|
||||
// from nsWindow.cpp
|
||||
extern bool gDisableNativeTheme;
|
||||
|
||||
static nsresult
|
||||
nsNativeThemeGTKConstructor(nsISupports *aOuter, REFNSIID aIID,
|
||||
void **aResult)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsITheme> inst;
|
||||
|
||||
if (gDisableNativeTheme)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
|
||||
*aResult = nullptr;
|
||||
if (nullptr != aOuter) {
|
||||
rv = NS_ERROR_NO_AGGREGATION;
|
||||
return rv;
|
||||
}
|
||||
if (gfxPlatform::IsHeadless()) {
|
||||
inst = new HeadlessThemeGTK();
|
||||
} else {
|
||||
inst = new nsNativeThemeGTK();
|
||||
}
|
||||
if (nullptr == inst) {
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
return rv;
|
||||
}
|
||||
rv = inst->QueryInterface(aIID, aResult);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
#if defined(MOZ_X11)
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
@ -212,9 +174,7 @@ NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
|
||||
#endif
|
||||
NS_DEFINE_NAMED_CID(NS_HTMLFORMATCONVERTER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_BIDIKEYBOARD_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_THEMERENDERER_CID);
|
||||
#ifdef NS_PRINTING
|
||||
NS_DEFINE_NAMED_CID(NS_PRINTSETTINGSSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_PRINTER_ENUMERATOR_CID);
|
||||
|
@ -245,10 +205,8 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||
{ &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceConstructor, Module::MAIN_PROCESS_ONLY },
|
||||
#endif
|
||||
{ &kNS_HTMLFORMATCONVERTER_CID, false, nullptr, nsHTMLFormatConverterConstructor },
|
||||
{ &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor },
|
||||
{ &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor,
|
||||
Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_THEMERENDERER_CID, false, nullptr, nsNativeThemeGTKConstructor },
|
||||
#ifdef NS_PRINTING
|
||||
{ &kNS_PRINTSETTINGSSERVICE_CID, false, nullptr, nsPrintSettingsServiceGTKConstructor },
|
||||
{ &kNS_PRINTER_ENUMERATOR_CID, false, nullptr, nsPrinterEnumeratorGTKConstructor },
|
||||
|
@ -280,11 +238,8 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
|||
{ "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::MAIN_PROCESS_ONLY },
|
||||
#endif
|
||||
{ "@mozilla.org/widget/htmlformatconverter;1", &kNS_HTMLFORMATCONVERTER_CID },
|
||||
{ "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID,
|
||||
Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID,
|
||||
Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
|
||||
#ifdef NS_PRINTING
|
||||
{ "@mozilla.org/gfx/printsettings-service;1", &kNS_PRINTSETTINGSSERVICE_CID },
|
||||
{ "@mozilla.org/gfx/printerenumerator;1", &kNS_PRINTER_ENUMERATOR_CID },
|
||||
|
|
|
@ -2482,6 +2482,25 @@ nsIWidget::GetEditCommands(nsIWidget::NativeKeyBindingsType aType,
|
|||
MOZ_ASSERT(aCommands.IsEmpty());
|
||||
}
|
||||
|
||||
already_AddRefed<nsIBidiKeyboard>
|
||||
nsIWidget::CreateBidiKeyboard()
|
||||
{
|
||||
if (XRE_IsContentProcess()) {
|
||||
return CreateBidiKeyboardContentProcess();
|
||||
} else {
|
||||
return CreateBidiKeyboardInner();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ANDROID
|
||||
already_AddRefed<nsIBidiKeyboard>
|
||||
nsIWidget::CreateBidiKeyboardInner()
|
||||
{
|
||||
// no bidi keyboard implementation
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace widget {
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "nsDragServiceProxy.h"
|
||||
#include "nsFilePickerProxy.h"
|
||||
#include "nsSoundProxy.h"
|
||||
#include "mozilla/widget/PuppetBidiKeyboard.h"
|
||||
#include "mozilla/widget/ScreenManager.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
@ -23,7 +22,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy)
|
|||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragServiceProxy)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsFilePickerProxy)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSoundProxy)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(PuppetBidiKeyboard)
|
||||
NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(ScreenManager, ScreenManager::GetAddRefedSingleton)
|
||||
|
||||
NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
|
||||
|
@ -31,7 +29,6 @@ NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_FILEPICKER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SOUND_CID);
|
||||
NS_DEFINE_NAMED_CID(PUPPETBIDIKEYBOARD_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
||||
|
@ -45,8 +42,6 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||
Module::CONTENT_PROCESS_ONLY },
|
||||
{ &kNS_SOUND_CID, false, nullptr, nsSoundProxyConstructor,
|
||||
Module::CONTENT_PROCESS_ONLY },
|
||||
{ &kPUPPETBIDIKEYBOARD_CID, false, NULL, PuppetBidiKeyboardConstructor,
|
||||
Module::CONTENT_PROCESS_ONLY },
|
||||
{ &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor,
|
||||
Module::CONTENT_PROCESS_ONLY },
|
||||
{ nullptr }
|
||||
|
@ -59,8 +54,6 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
|||
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, Module::CONTENT_PROCESS_ONLY },
|
||||
{ "@mozilla.org/sound;1", &kNS_SOUND_CID, Module::CONTENT_PROCESS_ONLY },
|
||||
{ "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::CONTENT_PROCESS_ONLY },
|
||||
{ "@mozilla.org/widget/bidikeyboard;1", &kPUPPETBIDIKEYBOARD_CID,
|
||||
Module::CONTENT_PROCESS_ONLY },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "Units.h"
|
||||
|
||||
// forward declarations
|
||||
class nsIBidiKeyboard;
|
||||
class nsIRollupListener;
|
||||
class imgIContainer;
|
||||
class nsIContent;
|
||||
|
@ -1746,6 +1747,9 @@ private:
|
|||
|
||||
static void OnLongTapTimerCallback(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
static already_AddRefed<nsIBidiKeyboard> CreateBidiKeyboardContentProcess();
|
||||
static already_AddRefed<nsIBidiKeyboard> CreateBidiKeyboardInner();
|
||||
|
||||
mozilla::UniquePtr<LongTapInfo> mLongTapTouchPoint;
|
||||
nsCOMPtr<nsITimer> mLongTapTimer;
|
||||
static int32_t sPointerIdCounter;
|
||||
|
@ -2133,6 +2137,8 @@ public:
|
|||
virtual void RecvScreenPixels(mozilla::ipc::Shmem&& aMem, const ScreenIntSize& aSize) = 0;
|
||||
#endif
|
||||
|
||||
static already_AddRefed<nsIBidiKeyboard> CreateBidiKeyboard();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Like GetDefaultScale, but taking into account only the system settings
|
||||
|
|
|
@ -104,13 +104,6 @@
|
|||
#define NS_SOUND_CID \
|
||||
{ 0xb148eed2, 0x236d, 0x11d3, { 0xb3, 0x5c, 0x0, 0xa0, 0xcc, 0x3c, 0x1c, 0xde } }
|
||||
|
||||
// {9f1800ab-f428-4207-b40c-e832e77b01fc}
|
||||
#define NS_BIDIKEYBOARD_CID \
|
||||
{ 0x9f1800ab, 0xf428, 0x4207, { 0xb4, 0x0c, 0xe8, 0x32, 0xe7, 0x7b, 0x01, 0xfc } }
|
||||
|
||||
#define PUPPETBIDIKEYBOARD_CID \
|
||||
{ 0x689e2586, 0x0344, 0x40b2, {0x83, 0x75, 0x13, 0x67, 0x2d, 0x3b, 0x71, 0x9a } }
|
||||
|
||||
#define NS_SCREENMANAGER_CID \
|
||||
{ 0xc401eb80, 0xf9ea, 0x11d3, { 0xbb, 0x6f, 0xe7, 0x32, 0xb7, 0x3e, 0xbe, 0x7c } }
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <stdio.h>
|
||||
#include "nsBidiKeyboard.h"
|
||||
#include "WidgetUtils.h"
|
||||
#include "nsIWidget.h"
|
||||
#include <tchar.h>
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsBidiKeyboard, nsIBidiKeyboard)
|
||||
|
@ -184,3 +185,10 @@ nsBidiKeyboard::OnLayoutChange()
|
|||
{
|
||||
mozilla::widget::WidgetUtils::SendBidiKeyboardInfoToContent();
|
||||
}
|
||||
|
||||
// static
|
||||
already_AddRefed<nsIBidiKeyboard>
|
||||
nsIWidget::CreateBidiKeyboardInner()
|
||||
{
|
||||
return do_AddRef(new nsBidiKeyboard());
|
||||
}
|
||||
|
|
|
@ -4446,16 +4446,12 @@ nsNativeThemeWin::DrawCustomScrollbarPart(gfxContext* aContext,
|
|||
// from nsWindow.cpp
|
||||
extern bool gDisableNativeTheme;
|
||||
|
||||
nsresult NS_NewNativeTheme(nsISupports *aOuter, REFNSIID aIID, void **aResult)
|
||||
already_AddRefed<nsITheme>
|
||||
NS_NewNativeTheme()
|
||||
{
|
||||
if (gDisableNativeTheme)
|
||||
return NS_ERROR_NO_INTERFACE;
|
||||
return nullptr;
|
||||
|
||||
if (aOuter)
|
||||
return NS_ERROR_NO_AGGREGATION;
|
||||
|
||||
nsNativeThemeWin* theme = new nsNativeThemeWin();
|
||||
if (!theme)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
return theme->QueryInterface(aIID, aResult);
|
||||
nsCOMPtr<nsITheme> theme = new nsNativeThemeWin();
|
||||
return theme.forget();
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
// Desktop
|
||||
#include "nsFilePicker.h" // needs to be included before other shobjidl.h includes
|
||||
#include "nsColorPicker.h"
|
||||
#include "nsNativeThemeWin.h"
|
||||
// Content processes
|
||||
#include "nsFilePickerProxy.h"
|
||||
|
||||
|
@ -35,7 +34,6 @@
|
|||
#include "nsClipboardHelper.h"
|
||||
#include "nsClipboard.h"
|
||||
#include "HeadlessClipboard.h"
|
||||
#include "nsBidiKeyboard.h"
|
||||
#include "nsDragService.h"
|
||||
#include "nsTransferable.h"
|
||||
#include "nsHTMLFormatConverter.h"
|
||||
|
@ -112,7 +110,6 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(WindowsUIUtils)
|
|||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsTransferable)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsHTMLFormatConverter)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDragService)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsBidiKeyboard)
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(TaskbarPreviewCallback)
|
||||
#ifdef NS_PRINTING
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsPrintDialogServiceWin, Init)
|
||||
|
@ -134,7 +131,6 @@ NS_DEFINE_NAMED_CID(NS_COLORPICKER_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_APPSHELL_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_SCREENMANAGER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_THEMERENDERER_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CLIPBOARD_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_CLIPBOARDHELPER_CID);
|
||||
|
@ -149,7 +145,6 @@ NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTLINK_CID);
|
|||
NS_DEFINE_NAMED_CID(NS_WIN_JUMPLISTSHORTCUT_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_WINDOWS_UIUTILS_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_DRAGSERVICE_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_BIDIKEYBOARD_CID);
|
||||
NS_DEFINE_NAMED_CID(NS_TASKBARPREVIEWCALLBACK_CID);
|
||||
#ifdef NS_PRINTING
|
||||
NS_DEFINE_NAMED_CID(NS_PRINTDIALOGSERVICE_CID);
|
||||
|
@ -167,7 +162,6 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||
{ &kNS_SCREENMANAGER_CID, false, nullptr, ScreenManagerConstructor,
|
||||
Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_GFXINFO_CID, false, nullptr, GfxInfoConstructor, Module::ALLOW_IN_GPU_PROCESS },
|
||||
{ &kNS_THEMERENDERER_CID, false, nullptr, NS_NewNativeTheme },
|
||||
{ &kNS_IDLE_SERVICE_CID, false, nullptr, nsIdleServiceWinConstructor },
|
||||
{ &kNS_CLIPBOARD_CID, false, nullptr, nsClipboardConstructor, Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_CLIPBOARDHELPER_CID, false, nullptr, nsClipboardHelperConstructor },
|
||||
|
@ -182,7 +176,6 @@ static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
|
|||
{ &kNS_WIN_JUMPLISTSHORTCUT_CID, false, nullptr, JumpListShortcutConstructor },
|
||||
{ &kNS_WINDOWS_UIUTILS_CID, false, nullptr, WindowsUIUtilsConstructor },
|
||||
{ &kNS_DRAGSERVICE_CID, false, nullptr, nsDragServiceConstructor, Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_BIDIKEYBOARD_CID, false, nullptr, nsBidiKeyboardConstructor, Module::MAIN_PROCESS_ONLY },
|
||||
{ &kNS_TASKBARPREVIEWCALLBACK_CID, false, nullptr, TaskbarPreviewCallbackConstructor },
|
||||
#ifdef NS_PRINTING
|
||||
{ &kNS_PRINTDIALOGSERVICE_CID, false, nullptr, nsPrintDialogServiceWinConstructor, Module::MAIN_PROCESS_ONLY },
|
||||
|
@ -200,7 +193,6 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
|||
{ "@mozilla.org/widget/appshell/win;1", &kNS_APPSHELL_CID, Module::ALLOW_IN_GPU_PROCESS },
|
||||
{ "@mozilla.org/gfx/screenmanager;1", &kNS_SCREENMANAGER_CID, Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID, Module::ALLOW_IN_GPU_PROCESS },
|
||||
{ "@mozilla.org/chrome/chrome-native-theme;1", &kNS_THEMERENDERER_CID },
|
||||
{ "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
|
||||
{ "@mozilla.org/widget/clipboard;1", &kNS_CLIPBOARD_CID, Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/widget/clipboardhelper;1", &kNS_CLIPBOARDHELPER_CID },
|
||||
|
@ -215,7 +207,6 @@ static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
|
|||
{ "@mozilla.org/windows-jumplistshortcut;1", &kNS_WIN_JUMPLISTSHORTCUT_CID },
|
||||
{ "@mozilla.org/windows-ui-utils;1", &kNS_WINDOWS_UIUTILS_CID },
|
||||
{ "@mozilla.org/widget/dragservice;1", &kNS_DRAGSERVICE_CID, Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/widget/bidikeyboard;1", &kNS_BIDIKEYBOARD_CID, Module::MAIN_PROCESS_ONLY },
|
||||
{ "@mozilla.org/widget/taskbar-preview-callback;1", &kNS_TASKBARPREVIEWCALLBACK_CID },
|
||||
#ifdef NS_PRINTING
|
||||
{ NS_PRINTDIALOGSERVICE_CONTRACTID, &kNS_PRINTDIALOGSERVICE_CID },
|
||||
|
|
|
@ -21,7 +21,6 @@ using namespace mozilla;
|
|||
TEST(TestEventTargetQI, ThreadPool)
|
||||
{
|
||||
nsCOMPtr<nsIThreadPool> thing = new nsThreadPool();
|
||||
EXPECT_TRUE(thing);
|
||||
|
||||
nsCOMPtr<nsISerialEventTarget> serial = do_QueryInterface(thing);
|
||||
EXPECT_FALSE(serial);
|
||||
|
|
|
@ -50,7 +50,6 @@ mozilla::Atomic<int> Task::sCount;
|
|||
TEST(ThreadPool, Main)
|
||||
{
|
||||
nsCOMPtr<nsIThreadPool> pool = new nsThreadPool();
|
||||
EXPECT_TRUE(pool);
|
||||
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
nsCOMPtr<nsIRunnable> task = new Task(i);
|
||||
|
@ -66,7 +65,6 @@ TEST(ThreadPool, Main)
|
|||
TEST(ThreadPool, Parallelism)
|
||||
{
|
||||
nsCOMPtr<nsIThreadPool> pool = new nsThreadPool();
|
||||
EXPECT_TRUE(pool);
|
||||
|
||||
// Dispatch and sleep to ensure we have an idle thread
|
||||
nsCOMPtr<nsIRunnable> r0 = new Runnable("TestRunnable");
|
||||
|
|
|
@ -472,7 +472,7 @@ nsWebShellWindow::WindowActivated()
|
|||
|
||||
// focusing the window could cause it to close, so keep a reference to it
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = mDocShell ? mDocShell->GetWindow() : nullptr;
|
||||
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm && window)
|
||||
fm->WindowRaised(window);
|
||||
|
||||
|
@ -489,8 +489,8 @@ nsWebShellWindow::WindowDeactivated()
|
|||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window =
|
||||
mDocShell ? mDocShell->GetWindow() : nullptr;
|
||||
nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
|
||||
if (fm && window)
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm && window && !fm->IsTestMode())
|
||||
fm->WindowLowered(window);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче