Bug 1914895 - Make Symbol.unscopables support optional for non-syntactic with-environments. r=arai
In D220213 we tried to change `Symbol.unscopables` so that it's only supported on syntactic `with` environments (for performance reasons). This failed some WPT tests for event handlers because they use non-syntactic with-environments but have to support `Symbol.unscopables`. This patch adds a `JS::EnvironmentChain` class and uses it instead of an object vector for some JS APIs. This class also lets the embedder specify whether `Symbol.unscopables` must be supported. The `evaluate` shell function now has an option for this too. Differential Revision: https://phabricator.services.mozilla.com/D226139
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
#include "js/CallAndConstruct.h" // JS::IsCallable, JS_CallFunctionValue
|
#include "js/CallAndConstruct.h" // JS::IsCallable, JS_CallFunctionValue
|
||||||
#include "js/CompilationAndEvaluation.h"
|
#include "js/CompilationAndEvaluation.h"
|
||||||
#include "js/CompileOptions.h"
|
#include "js/CompileOptions.h"
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/experimental/JSStencil.h"
|
#include "js/experimental/JSStencil.h"
|
||||||
#include "js/GCVector.h"
|
#include "js/GCVector.h"
|
||||||
#include "js/JSON.h"
|
#include "js/JSON.h"
|
||||||
@@ -1212,7 +1213,7 @@ void nsMessageManagerScriptExecutor::LoadScriptInternal(
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
JS::Rooted<JS::Value> rval(cx);
|
JS::Rooted<JS::Value> rval(cx);
|
||||||
JS::RootedVector<JSObject*> envChain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No);
|
||||||
if (!envChain.append(aMessageManager)) {
|
if (!envChain.append(aMessageManager)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "js/CompilationAndEvaluation.h"
|
#include "js/CompilationAndEvaluation.h"
|
||||||
#include "js/CompileOptions.h"
|
#include "js/CompileOptions.h"
|
||||||
#include "js/Date.h"
|
#include "js/Date.h"
|
||||||
|
#include "js/EnvironmentChain.h"
|
||||||
#include "js/GCVector.h"
|
#include "js/GCVector.h"
|
||||||
#include "js/HeapAPI.h"
|
#include "js/HeapAPI.h"
|
||||||
#include "js/Modules.h"
|
#include "js/Modules.h"
|
||||||
@@ -80,7 +81,7 @@ nsresult nsJSUtils::UpdateFunctionDebugMetadata(
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
|
nsresult nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
|
||||||
JS::HandleVector<JSObject*> aScopeChain,
|
const JS::EnvironmentChain& aEnvChain,
|
||||||
JS::CompileOptions& aOptions,
|
JS::CompileOptions& aOptions,
|
||||||
const nsACString& aName, uint32_t aArgCount,
|
const nsACString& aName, uint32_t aArgCount,
|
||||||
const char** aArgArray,
|
const char** aArgArray,
|
||||||
@@ -88,12 +89,12 @@ nsresult nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
|
|||||||
JSObject** aFunctionObject) {
|
JSObject** aFunctionObject) {
|
||||||
JSContext* cx = jsapi.cx();
|
JSContext* cx = jsapi.cx();
|
||||||
MOZ_ASSERT(js::GetContextRealm(cx));
|
MOZ_ASSERT(js::GetContextRealm(cx));
|
||||||
MOZ_ASSERT_IF(aScopeChain.length() != 0,
|
MOZ_ASSERT_IF(aEnvChain.length() != 0,
|
||||||
js::IsObjectInContextCompartment(aScopeChain[0], cx));
|
js::IsObjectInContextCompartment(aEnvChain.chain()[0], cx));
|
||||||
|
|
||||||
// Do the junk Gecko is supposed to do before calling into JSAPI.
|
// Do the junk Gecko is supposed to do before calling into JSAPI.
|
||||||
for (size_t i = 0; i < aScopeChain.length(); ++i) {
|
for (size_t i = 0; i < aEnvChain.length(); ++i) {
|
||||||
JS::ExposeObjectToActiveJS(aScopeChain[i]);
|
JS::ExposeObjectToActiveJS(aEnvChain.chain()[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile.
|
// Compile.
|
||||||
@@ -106,7 +107,7 @@ nsresult nsJSUtils::CompileFunction(AutoJSAPI& jsapi,
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS::Rooted<JSFunction*> fun(
|
JS::Rooted<JSFunction*> fun(
|
||||||
cx, JS::CompileFunction(cx, aScopeChain, aOptions,
|
cx, JS::CompileFunction(cx, aEnvChain, aOptions,
|
||||||
PromiseFlatCString(aName).get(), aArgCount,
|
PromiseFlatCString(aName).get(), aArgCount,
|
||||||
aArgArray, source));
|
aArgArray, source));
|
||||||
if (!fun) {
|
if (!fun) {
|
||||||
@@ -122,14 +123,14 @@ bool nsJSUtils::IsScriptable(JS::Handle<JSObject*> aEvaluationGlobal) {
|
|||||||
return xpc::Scriptability::AllowedIfExists(aEvaluationGlobal);
|
return xpc::Scriptability::AllowedIfExists(aEvaluationGlobal);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool AddScopeChainItem(JSContext* aCx, nsINode* aNode,
|
static bool AddEnvChainItem(JSContext* aCx, nsINode* aNode,
|
||||||
JS::MutableHandleVector<JSObject*> aScopeChain) {
|
JS::EnvironmentChain& aEnvChain) {
|
||||||
JS::Rooted<JS::Value> val(aCx);
|
JS::Rooted<JS::Value> val(aCx);
|
||||||
if (!GetOrCreateDOMReflector(aCx, aNode, &val)) {
|
if (!GetOrCreateDOMReflector(aCx, aNode, &val)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!aScopeChain.append(&val.toObject())) {
|
if (!aEnvChain.append(&val.toObject())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,11 +138,10 @@ static bool AddScopeChainItem(JSContext* aCx, nsINode* aNode,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
bool nsJSUtils::GetScopeChainForElement(
|
bool nsJSUtils::GetEnvironmentChainForElement(JSContext* aCx, Element* aElement,
|
||||||
JSContext* aCx, Element* aElement,
|
JS::EnvironmentChain& aEnvChain) {
|
||||||
JS::MutableHandleVector<JSObject*> aScopeChain) {
|
|
||||||
for (nsINode* cur = aElement; cur; cur = cur->GetScopeChainParent()) {
|
for (nsINode* cur = aElement; cur; cur = cur->GetScopeChainParent()) {
|
||||||
if (!AddScopeChainItem(aCx, cur, aScopeChain)) {
|
if (!AddEnvChainItem(aCx, cur, aEnvChain)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ class nsIScriptElement;
|
|||||||
class nsIScriptGlobalObject;
|
class nsIScriptGlobalObject;
|
||||||
class nsXBLPrototypeBinding;
|
class nsXBLPrototypeBinding;
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
class JS_PUBLIC_API EnvironmentChain;
|
||||||
|
};
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
union Utf8Unit;
|
union Utf8Unit;
|
||||||
|
|
||||||
@@ -51,7 +55,7 @@ class nsJSUtils {
|
|||||||
static uint64_t GetCurrentlyRunningCodeInnerWindowID(JSContext* aContext);
|
static uint64_t GetCurrentlyRunningCodeInnerWindowID(JSContext* aContext);
|
||||||
|
|
||||||
static nsresult CompileFunction(mozilla::dom::AutoJSAPI& jsapi,
|
static nsresult CompileFunction(mozilla::dom::AutoJSAPI& jsapi,
|
||||||
JS::HandleVector<JSObject*> aScopeChain,
|
const JS::EnvironmentChain& aEnvChain,
|
||||||
JS::CompileOptions& aOptions,
|
JS::CompileOptions& aOptions,
|
||||||
const nsACString& aName, uint32_t aArgCount,
|
const nsACString& aName, uint32_t aArgCount,
|
||||||
const char** aArgArray,
|
const char** aArgArray,
|
||||||
@@ -66,10 +70,10 @@ class nsJSUtils {
|
|||||||
static bool IsScriptable(JS::Handle<JSObject*> aEvaluationGlobal);
|
static bool IsScriptable(JS::Handle<JSObject*> aEvaluationGlobal);
|
||||||
|
|
||||||
// Returns false if an exception got thrown on aCx. Passing a null
|
// Returns false if an exception got thrown on aCx. Passing a null
|
||||||
// aElement is allowed; that wil produce an empty aScopeChain.
|
// aElement is allowed; that wil produce an empty aEnvChain.
|
||||||
static bool GetScopeChainForElement(
|
static bool GetEnvironmentChainForElement(JSContext* aCx,
|
||||||
JSContext* aCx, mozilla::dom::Element* aElement,
|
mozilla::dom::Element* aElement,
|
||||||
JS::MutableHandleVector<JSObject*> aScopeChain);
|
JS::EnvironmentChain& aEnvChain);
|
||||||
|
|
||||||
static void ResetTimeZone();
|
static void ResetTimeZone();
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#undef CreateEvent
|
#undef CreateEvent
|
||||||
|
|
||||||
#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
|
#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/loader/LoadedScript.h"
|
#include "js/loader/LoadedScript.h"
|
||||||
#include "js/loader/ScriptFetchOptions.h"
|
#include "js/loader/ScriptFetchOptions.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
@@ -1219,12 +1220,12 @@ nsresult EventListenerManager::CompileEventHandlerInternal(
|
|||||||
JSAutoRealm ar(cx, target);
|
JSAutoRealm ar(cx, target);
|
||||||
|
|
||||||
// Now that we've entered the realm we actually care about, create our
|
// Now that we've entered the realm we actually care about, create our
|
||||||
// scope chain. Note that we start with |element|, not aElement, because
|
// environment chain. Note that we start with |element|, not aElement,
|
||||||
// mTarget is different from aElement in the <body> case, where mTarget is a
|
// because mTarget is different from aElement in the <body> case, where
|
||||||
// Window, and in that case we do not want the scope chain to include the body
|
// mTarget is a Window, and in that case we do not want the environment chain
|
||||||
// or the document.
|
// to include the body or the document.
|
||||||
JS::RootedVector<JSObject*> scopeChain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::Yes);
|
||||||
if (!nsJSUtils::GetScopeChainForElement(cx, element, &scopeChain)) {
|
if (!nsJSUtils::GetEnvironmentChainForElement(cx, element, envChain)) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1257,7 +1258,7 @@ nsresult EventListenerManager::CompileEventHandlerInternal(
|
|||||||
.setDeferDebugMetadata(true);
|
.setDeferDebugMetadata(true);
|
||||||
|
|
||||||
JS::Rooted<JSObject*> handler(cx);
|
JS::Rooted<JSObject*> handler(cx);
|
||||||
result = nsJSUtils::CompileFunction(jsapi, scopeChain, options,
|
result = nsJSUtils::CompileFunction(jsapi, envChain, options,
|
||||||
nsAtomCString(aTypeAtom), argCount,
|
nsAtomCString(aTypeAtom), argCount,
|
||||||
argNames, *body, handler.address());
|
argNames, *body, handler.address());
|
||||||
NS_ENSURE_SUCCESS(result, result);
|
NS_ENSURE_SUCCESS(result, result);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ union Utf8Unit;
|
|||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
|
class JS_PUBLIC_API EnvironmentChain;
|
||||||
class JS_PUBLIC_API InstantiateOptions;
|
class JS_PUBLIC_API InstantiateOptions;
|
||||||
class JS_PUBLIC_API ReadOnlyCompileOptions;
|
class JS_PUBLIC_API ReadOnlyCompileOptions;
|
||||||
|
|
||||||
@@ -84,12 +85,12 @@ extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx,
|
|||||||
* objects that should end up on the script's scope chain.
|
* objects that should end up on the script's scope chain.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx,
|
extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx,
|
||||||
JS::HandleObjectVector envChain,
|
const JS::EnvironmentChain& envChain,
|
||||||
JS::Handle<JSScript*> script,
|
JS::Handle<JSScript*> script,
|
||||||
JS::MutableHandle<JS::Value> rval);
|
JS::MutableHandle<JS::Value> rval);
|
||||||
|
|
||||||
extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx,
|
extern JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx,
|
||||||
JS::HandleObjectVector envChain,
|
const JS::EnvironmentChain& envChain,
|
||||||
JS::Handle<JSScript*> script);
|
JS::Handle<JSScript*> script);
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
@@ -108,7 +109,8 @@ extern JS_PUBLIC_API bool Evaluate(JSContext* cx,
|
|||||||
* the global object on it; that's implicit. It needs to contain the other
|
* the global object on it; that's implicit. It needs to contain the other
|
||||||
* objects that should end up on the script's scope chain.
|
* objects that should end up on the script's scope chain.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API bool Evaluate(JSContext* cx, HandleObjectVector envChain,
|
extern JS_PUBLIC_API bool Evaluate(JSContext* cx,
|
||||||
|
const JS::EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& options,
|
const ReadOnlyCompileOptions& options,
|
||||||
SourceText<char16_t>& srcBuf,
|
SourceText<char16_t>& srcBuf,
|
||||||
MutableHandle<Value> rval);
|
MutableHandle<Value> rval);
|
||||||
@@ -173,7 +175,7 @@ extern JS_PUBLIC_API JSScript* CompileUtf8Path(
|
|||||||
* global must not be explicitly included in the scope chain.
|
* global must not be explicitly included in the scope chain.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API JSFunction* CompileFunction(
|
extern JS_PUBLIC_API JSFunction* CompileFunction(
|
||||||
JSContext* cx, HandleObjectVector envChain,
|
JSContext* cx, const JS::EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
||||||
const char* const* argnames, SourceText<char16_t>& srcBuf);
|
const char* const* argnames, SourceText<char16_t>& srcBuf);
|
||||||
|
|
||||||
@@ -185,7 +187,7 @@ extern JS_PUBLIC_API JSFunction* CompileFunction(
|
|||||||
* global must not be explicitly included in the scope chain.
|
* global must not be explicitly included in the scope chain.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API JSFunction* CompileFunction(
|
extern JS_PUBLIC_API JSFunction* CompileFunction(
|
||||||
JSContext* cx, HandleObjectVector envChain,
|
JSContext* cx, const JS::EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
||||||
const char* const* argnames, SourceText<mozilla::Utf8Unit>& srcBuf);
|
const char* const* argnames, SourceText<mozilla::Utf8Unit>& srcBuf);
|
||||||
|
|
||||||
@@ -194,7 +196,7 @@ extern JS_PUBLIC_API JSFunction* CompileFunction(
|
|||||||
* Rust-friendly ergonomics.
|
* Rust-friendly ergonomics.
|
||||||
*/
|
*/
|
||||||
extern JS_PUBLIC_API JSFunction* CompileFunctionUtf8(
|
extern JS_PUBLIC_API JSFunction* CompileFunctionUtf8(
|
||||||
JSContext* cx, HandleObjectVector envChain,
|
JSContext* cx, const JS::EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
||||||
const char* const* argnames, const char* utf8, size_t length);
|
const char* const* argnames, const char* utf8, size_t length);
|
||||||
|
|
||||||
|
|||||||
67
js/public/EnvironmentChain.h
Normal file
67
js/public/EnvironmentChain.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; 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/. */
|
||||||
|
|
||||||
|
#ifndef js_EnvironmentChain_h
|
||||||
|
#define js_EnvironmentChain_h
|
||||||
|
|
||||||
|
#include "mozilla/Attributes.h" // MOZ_RAII
|
||||||
|
|
||||||
|
#include <stddef.h> // size_t
|
||||||
|
|
||||||
|
#include "jstypes.h" // JS_PUBLIC_API
|
||||||
|
|
||||||
|
#include "js/GCVector.h" // JS::RootedVector
|
||||||
|
|
||||||
|
struct JS_PUBLIC_API JSContext;
|
||||||
|
class JS_PUBLIC_API JSObject;
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
|
||||||
|
enum class SupportUnscopables : bool { No = false, Yes = true };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JS::EnvironmentChain stores a list of objects to put on the environment
|
||||||
|
* chain.
|
||||||
|
*
|
||||||
|
* Internally the engine will create a non-syntactic 'with' environment for each
|
||||||
|
* of these objects. Note that 'with' environments aren't optimized well so you
|
||||||
|
* should use this class only if you really have to.
|
||||||
|
*
|
||||||
|
* The SupportUnscopables enum class controls whether these non-syntactic 'with'
|
||||||
|
* environments support Symbol.unscopables similar to syntactic 'with'
|
||||||
|
* statements in JS.
|
||||||
|
*
|
||||||
|
* Passing SupportUnscopables::No is better for performance because it lets us
|
||||||
|
* skip the Symbol.unscopables property lookup. Some Web APIs require supporting
|
||||||
|
* Symbol.unscopables though. In Firefox, SupportUnscopables::Yes is used for
|
||||||
|
* event handlers.
|
||||||
|
*/
|
||||||
|
class MOZ_RAII JS_PUBLIC_API EnvironmentChain {
|
||||||
|
JS::RootedObjectVector chain_;
|
||||||
|
SupportUnscopables supportUnscopables_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EnvironmentChain(JSContext* cx, SupportUnscopables supportUnscopables)
|
||||||
|
: chain_(cx), supportUnscopables_(supportUnscopables) {}
|
||||||
|
|
||||||
|
EnvironmentChain(const EnvironmentChain&) = delete;
|
||||||
|
void operator=(const EnvironmentChain&) = delete;
|
||||||
|
|
||||||
|
[[nodiscard]] bool append(JSObject* obj) { return chain_.append(obj); }
|
||||||
|
bool empty() const { return chain_.empty(); }
|
||||||
|
size_t length() const { return chain_.length(); }
|
||||||
|
|
||||||
|
RootedObjectVector& chain() { return chain_; }
|
||||||
|
const RootedObjectVector& chain() const { return chain_; }
|
||||||
|
|
||||||
|
void setSupportUnscopables(SupportUnscopables supportUnscopables) {
|
||||||
|
supportUnscopables_ = supportUnscopables;
|
||||||
|
}
|
||||||
|
SupportUnscopables supportUnscopables() const { return supportUnscopables_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace JS
|
||||||
|
|
||||||
|
#endif /* js_EnvironmentChain_h */
|
||||||
@@ -45,6 +45,8 @@
|
|||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
|
class JS_PUBLIC_API EnvironmentChain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate a new environment in the current compartment that is compatible with
|
* Allocate a new environment in the current compartment that is compatible with
|
||||||
* JSM shared loading.
|
* JSM shared loading.
|
||||||
@@ -68,7 +70,7 @@ extern JS_PUBLIC_API bool ExecuteInJSMEnvironment(JSContext* cx,
|
|||||||
// temporarily placed on the environment chain.
|
// temporarily placed on the environment chain.
|
||||||
extern JS_PUBLIC_API bool ExecuteInJSMEnvironment(
|
extern JS_PUBLIC_API bool ExecuteInJSMEnvironment(
|
||||||
JSContext* cx, Handle<JSScript*> script, Handle<JSObject*> jsmEnv,
|
JSContext* cx, Handle<JSScript*> script, Handle<JSObject*> jsmEnv,
|
||||||
Handle<StackGCVector<JSObject*>> targetObj);
|
const EnvironmentChain& targetObj);
|
||||||
|
|
||||||
// Used by native methods to determine the JSMEnvironment of caller if possible
|
// Used by native methods to determine the JSMEnvironment of caller if possible
|
||||||
// by looking at stack frames. Returns nullptr if top frame isn't a scripted
|
// by looking at stack frames. Returns nullptr if top frame isn't a scripted
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "frontend/BytecodeCompiler.h" // frontend::CompileEvalScript
|
#include "frontend/BytecodeCompiler.h" // frontend::CompileEvalScript
|
||||||
#include "gc/HashUtil.h"
|
#include "gc/HashUtil.h"
|
||||||
#include "js/CompilationAndEvaluation.h"
|
#include "js/CompilationAndEvaluation.h"
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||||
#include "js/friend/JSMEnvironment.h" // JS::NewJSMEnvironment, JS::ExecuteInJSMEnvironment, JS::GetJSMEnvironmentOfScriptedCaller, JS::IsJSMEnvironment
|
#include "js/friend/JSMEnvironment.h" // JS::NewJSMEnvironment, JS::ExecuteInJSMEnvironment, JS::GetJSMEnvironmentOfScriptedCaller, JS::IsJSMEnvironment
|
||||||
#include "js/friend/WindowProxy.h" // js::IsWindowProxy
|
#include "js/friend/WindowProxy.h" // js::IsWindowProxy
|
||||||
@@ -410,7 +411,7 @@ JS_PUBLIC_API bool js::ExecuteInFrameScriptEnvironment(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedObjectVector envChain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No);
|
||||||
if (!envChain.append(objArg)) {
|
if (!envChain.append(objArg)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -461,14 +462,13 @@ JS_PUBLIC_API JSObject* JS::NewJSMEnvironment(JSContext* cx) {
|
|||||||
JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx,
|
JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx,
|
||||||
HandleScript scriptArg,
|
HandleScript scriptArg,
|
||||||
HandleObject varEnv) {
|
HandleObject varEnv) {
|
||||||
RootedObjectVector emptyChain(cx);
|
JS::EnvironmentChain emptyChain(cx, JS::SupportUnscopables::No);
|
||||||
return ExecuteInJSMEnvironment(cx, scriptArg, varEnv, emptyChain);
|
return ExecuteInJSMEnvironment(cx, scriptArg, varEnv, emptyChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(JSContext* cx,
|
JS_PUBLIC_API bool JS::ExecuteInJSMEnvironment(
|
||||||
HandleScript scriptArg,
|
JSContext* cx, HandleScript scriptArg, HandleObject varEnv,
|
||||||
HandleObject varEnv,
|
const EnvironmentChain& targetObj) {
|
||||||
HandleObjectVector targetObj) {
|
|
||||||
cx->check(varEnv);
|
cx->check(varEnv);
|
||||||
MOZ_ASSERT(
|
MOZ_ASSERT(
|
||||||
ObjectRealm::get(varEnv).getNonSyntacticLexicalEnvironment(varEnv));
|
ObjectRealm::get(varEnv).getNonSyntacticLexicalEnvironment(varEnv));
|
||||||
|
|||||||
@@ -41,6 +41,7 @@
|
|||||||
#include "jit/JSJitFrameIter.h" // for InlineFrameIterator
|
#include "jit/JSJitFrameIter.h" // for InlineFrameIterator
|
||||||
#include "jit/RematerializedFrame.h" // for RematerializedFrame
|
#include "jit/RematerializedFrame.h" // for RematerializedFrame
|
||||||
#include "js/CallArgs.h" // for CallArgs
|
#include "js/CallArgs.h" // for CallArgs
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/friend/ErrorMessages.h" // for GetErrorMessage, JSMSG_*
|
#include "js/friend/ErrorMessages.h" // for GetErrorMessage, JSMSG_*
|
||||||
#include "js/GCVector.h" // for JS::StackGCVector
|
#include "js/GCVector.h" // for JS::StackGCVector
|
||||||
#include "js/Object.h" // for SetReservedSlot
|
#include "js/Object.h" // for SetReservedSlot
|
||||||
@@ -954,7 +955,7 @@ static WithEnvironmentObject* CreateBindingsEnv(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RootedObjectVector envChain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No);
|
||||||
if (!envChain.append(bindingsObj)) {
|
if (!envChain.append(bindingsObj)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#include "js/AllocPolicy.h" // js::SystemAllocPolicy, ReportOutOfMemory
|
#include "js/AllocPolicy.h" // js::SystemAllocPolicy, ReportOutOfMemory
|
||||||
#include "js/CharacterEncoding.h" // JS_EncodeStringToUTF8
|
#include "js/CharacterEncoding.h" // JS_EncodeStringToUTF8
|
||||||
#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
|
#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
|
||||||
|
#include "js/EnvironmentChain.h" // JS::SupportUnscopables
|
||||||
#include "js/ErrorReport.h" // JS_ReportErrorASCII
|
#include "js/ErrorReport.h" // JS_ReportErrorASCII
|
||||||
#include "js/experimental/JSStencil.h"
|
#include "js/experimental/JSStencil.h"
|
||||||
#include "js/GCVector.h" // JS::StackGCVector
|
#include "js/GCVector.h" // JS::StackGCVector
|
||||||
@@ -612,8 +613,8 @@ static WithEnvironmentObject* CreateExtraBindingsEnvironment(
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS::Rooted<JSObject*> globalLexical(cx, &cx->global()->lexicalEnvironment());
|
JS::Rooted<JSObject*> globalLexical(cx, &cx->global()->lexicalEnvironment());
|
||||||
return WithEnvironmentObject::createNonSyntactic(cx, extraBindingsObj,
|
return WithEnvironmentObject::createNonSyntactic(
|
||||||
globalLexical);
|
cx, extraBindingsObj, globalLexical, JS::SupportUnscopables::No);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSScript* frontend::CompileGlobalScriptWithExtraBindings(
|
JSScript* frontend::CompileGlobalScriptWithExtraBindings(
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// Tests evaluate's supportUnscopables option.
|
||||||
|
function test(supportUnscopables) {
|
||||||
|
var env = {x: 1, y: 2};
|
||||||
|
Object.defineProperty(env, Symbol.unscopables, {get: function() {
|
||||||
|
assertEq(supportUnscopables, true);
|
||||||
|
return {x: false, y: true};
|
||||||
|
}});
|
||||||
|
|
||||||
|
evaluate(`this.gotX = x; try { this.gotY = y; } catch {}`,
|
||||||
|
{envChainObject: env, supportUnscopables});
|
||||||
|
assertEq(env.gotX, 1);
|
||||||
|
assertEq(env.gotY, supportUnscopables ? undefined : 2);
|
||||||
|
}
|
||||||
|
test(false);
|
||||||
|
test(true);
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "js/CallAndConstruct.h" // JS_CallFunctionValue
|
#include "js/CallAndConstruct.h" // JS_CallFunctionValue
|
||||||
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
|
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
|
||||||
#include "js/ContextOptions.h"
|
#include "js/ContextOptions.h"
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/GlobalObject.h" // JS_NewGlobalObject
|
#include "js/GlobalObject.h" // JS_NewGlobalObject
|
||||||
#include "js/PropertyAndElement.h" // JS_DefineProperty
|
#include "js/PropertyAndElement.h" // JS_DefineProperty
|
||||||
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
||||||
@@ -87,8 +88,8 @@ BEGIN_TEST(testChromeBuffer) {
|
|||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine("", 0);
|
options.setFileAndLine("", 0);
|
||||||
|
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "trusted", 1,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, "trusted", 1,
|
||||||
¶mName, srcBuf);
|
¶mName, srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
|
CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
|
||||||
@@ -118,8 +119,8 @@ BEGIN_TEST(testChromeBuffer) {
|
|||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine("", 0);
|
options.setFileAndLine("", 0);
|
||||||
|
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "untrusted", 1,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, "untrusted", 1,
|
||||||
¶mName, srcBuf);
|
¶mName, srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
CHECK(JS_DefineProperty(cx, global, "untrusted", fun, JSPROP_ENUMERATE));
|
CHECK(JS_DefineProperty(cx, global, "untrusted", fun, JSPROP_ENUMERATE));
|
||||||
@@ -165,8 +166,8 @@ BEGIN_TEST(testChromeBuffer) {
|
|||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine("", 0);
|
options.setFileAndLine("", 0);
|
||||||
|
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "trusted", 1,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, "trusted", 1,
|
||||||
¶mName, srcBuf);
|
¶mName, srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
|
CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
|
||||||
@@ -192,8 +193,8 @@ BEGIN_TEST(testChromeBuffer) {
|
|||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine("", 0);
|
options.setFileAndLine("", 0);
|
||||||
|
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "untrusted", 1,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, "untrusted", 1,
|
||||||
¶mName, srcBuf);
|
¶mName, srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
CHECK(JS_DefineProperty(cx, global, "untrusted", fun, JSPROP_ENUMERATE));
|
CHECK(JS_DefineProperty(cx, global, "untrusted", fun, JSPROP_ENUMERATE));
|
||||||
@@ -226,8 +227,8 @@ BEGIN_TEST(testChromeBuffer) {
|
|||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine("", 0);
|
options.setFileAndLine("", 0);
|
||||||
|
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "trusted", 0,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, "trusted", 0,
|
||||||
nullptr, srcBuf);
|
nullptr, srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
|
CHECK(JS_DefineProperty(cx, trusted_glob, "trusted", fun,
|
||||||
@@ -254,8 +255,8 @@ BEGIN_TEST(testChromeBuffer) {
|
|||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine("", 0);
|
options.setFileAndLine("", 0);
|
||||||
|
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "untrusted", 1,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, "untrusted", 1,
|
||||||
¶mName, srcBuf);
|
¶mName, srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
CHECK(JS_DefineProperty(cx, global, "untrusted", fun, JSPROP_ENUMERATE));
|
CHECK(JS_DefineProperty(cx, global, "untrusted", fun, JSPROP_ENUMERATE));
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "js/CallAndConstruct.h"
|
#include "js/CallAndConstruct.h"
|
||||||
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
|
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
||||||
#include "jsapi-tests/tests.h"
|
#include "jsapi-tests/tests.h"
|
||||||
#include "util/Text.h"
|
#include "util/Text.h"
|
||||||
@@ -23,7 +24,7 @@ BEGIN_TEST(test_functionBinding) {
|
|||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine(__FILE__, __LINE__);
|
options.setFileAndLine(__FILE__, __LINE__);
|
||||||
|
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
|
|
||||||
// Named function shouldn't have it's binding.
|
// Named function shouldn't have it's binding.
|
||||||
{
|
{
|
||||||
@@ -33,7 +34,7 @@ BEGIN_TEST(test_functionBinding) {
|
|||||||
CHECK(srcBuf.init(cx, s1chars, js_strlen(s1chars),
|
CHECK(srcBuf.init(cx, s1chars, js_strlen(s1chars),
|
||||||
JS::SourceOwnership::Borrowed));
|
JS::SourceOwnership::Borrowed));
|
||||||
|
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "s1", 0, nullptr,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, "s1", 0, nullptr,
|
||||||
srcBuf);
|
srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
}
|
}
|
||||||
@@ -52,7 +53,7 @@ BEGIN_TEST(test_functionBinding) {
|
|||||||
CHECK(srcBuf.init(cx, s2chars, js_strlen(s2chars),
|
CHECK(srcBuf.init(cx, s2chars, js_strlen(s2chars),
|
||||||
JS::SourceOwnership::Borrowed));
|
JS::SourceOwnership::Borrowed));
|
||||||
|
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "s2", 0, nullptr,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, "s2", 0, nullptr,
|
||||||
srcBuf);
|
srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
}
|
}
|
||||||
@@ -69,7 +70,7 @@ BEGIN_TEST(test_functionBinding) {
|
|||||||
CHECK(srcBuf.init(cx, s3chars, js_strlen(s3chars),
|
CHECK(srcBuf.init(cx, s3chars, js_strlen(s3chars),
|
||||||
JS::SourceOwnership::Borrowed));
|
JS::SourceOwnership::Borrowed));
|
||||||
|
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, nullptr, 0, nullptr,
|
fun = JS::CompileFunction(cx, emptyEnvChain, options, nullptr, 0, nullptr,
|
||||||
srcBuf);
|
srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "js/CallAndConstruct.h"
|
#include "js/CallAndConstruct.h"
|
||||||
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
|
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/PropertyAndElement.h" // JS_DefineProperty
|
#include "js/PropertyAndElement.h" // JS_DefineProperty
|
||||||
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
||||||
#include "jsapi-tests/tests.h"
|
#include "jsapi-tests/tests.h"
|
||||||
@@ -22,7 +23,7 @@
|
|||||||
using namespace js;
|
using namespace js;
|
||||||
|
|
||||||
BEGIN_TEST(testFunctionNonSyntactic) {
|
BEGIN_TEST(testFunctionNonSyntactic) {
|
||||||
JS::RootedObjectVector scopeChain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No);
|
||||||
|
|
||||||
{
|
{
|
||||||
JS::RootedObject scopeObj(cx, JS_NewPlainObject(cx));
|
JS::RootedObject scopeObj(cx, JS_NewPlainObject(cx));
|
||||||
@@ -30,7 +31,7 @@ BEGIN_TEST(testFunctionNonSyntactic) {
|
|||||||
JS::RootedValue val(cx);
|
JS::RootedValue val(cx);
|
||||||
val.setNumber(1);
|
val.setNumber(1);
|
||||||
CHECK(JS_DefineProperty(cx, scopeObj, "foo", val, JSPROP_ENUMERATE));
|
CHECK(JS_DefineProperty(cx, scopeObj, "foo", val, JSPROP_ENUMERATE));
|
||||||
CHECK(scopeChain.append(scopeObj));
|
CHECK(envChain.append(scopeObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -39,7 +40,7 @@ BEGIN_TEST(testFunctionNonSyntactic) {
|
|||||||
JS::RootedValue val(cx);
|
JS::RootedValue val(cx);
|
||||||
val.setNumber(20);
|
val.setNumber(20);
|
||||||
CHECK(JS_DefineProperty(cx, scopeObj, "bar", val, JSPROP_ENUMERATE));
|
CHECK(JS_DefineProperty(cx, scopeObj, "bar", val, JSPROP_ENUMERATE));
|
||||||
CHECK(scopeChain.append(scopeObj));
|
CHECK(envChain.append(scopeObj));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -50,8 +51,8 @@ BEGIN_TEST(testFunctionNonSyntactic) {
|
|||||||
|
|
||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine(__FILE__, __LINE__);
|
options.setFileAndLine(__FILE__, __LINE__);
|
||||||
RootedFunction fun(cx, JS::CompileFunction(cx, scopeChain, options, "test",
|
RootedFunction fun(cx, JS::CompileFunction(cx, envChain, options, "test", 0,
|
||||||
0, nullptr, srcBuf));
|
nullptr, srcBuf));
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
|
|
||||||
CHECK(fun->enclosingScope()->kind() == ScopeKind::NonSyntactic);
|
CHECK(fun->enclosingScope()->kind() == ScopeKind::NonSyntactic);
|
||||||
@@ -76,8 +77,8 @@ BEGIN_TEST(testFunctionNonSyntactic) {
|
|||||||
|
|
||||||
JS::CompileOptions options(cx);
|
JS::CompileOptions options(cx);
|
||||||
options.setFileAndLine(__FILE__, __LINE__);
|
options.setFileAndLine(__FILE__, __LINE__);
|
||||||
RootedFunction fun(cx, JS::CompileFunction(cx, scopeChain, options, "test",
|
RootedFunction fun(cx, JS::CompileFunction(cx, envChain, options, "test", 1,
|
||||||
1, args, srcBuf));
|
args, srcBuf));
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
|
|
||||||
CHECK(fun->enclosingScope()->kind() == ScopeKind::NonSyntactic);
|
CHECK(fun->enclosingScope()->kind() == ScopeKind::NonSyntactic);
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "js/CompilationAndEvaluation.h"
|
#include "js/CompilationAndEvaluation.h"
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/PropertyAndElement.h" // JS_AlreadyHasOwnProperty, JS_HasProperty
|
#include "js/PropertyAndElement.h" // JS_AlreadyHasOwnProperty, JS_HasProperty
|
||||||
#include "js/SourceText.h"
|
#include "js/SourceText.h"
|
||||||
#include "jsapi-tests/tests.h"
|
#include "jsapi-tests/tests.h"
|
||||||
@@ -16,13 +17,13 @@ BEGIN_TEST(testJSEvaluateScript) {
|
|||||||
|
|
||||||
JS::RootedValue retval(cx);
|
JS::RootedValue retval(cx);
|
||||||
JS::CompileOptions opts(cx);
|
JS::CompileOptions opts(cx);
|
||||||
JS::RootedObjectVector scopeChain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No);
|
||||||
CHECK(scopeChain.append(obj));
|
CHECK(envChain.append(obj));
|
||||||
|
|
||||||
JS::SourceText<char16_t> srcBuf;
|
JS::SourceText<char16_t> srcBuf;
|
||||||
CHECK(srcBuf.init(cx, src, js_strlen(src), JS::SourceOwnership::Borrowed));
|
CHECK(srcBuf.init(cx, src, js_strlen(src), JS::SourceOwnership::Borrowed));
|
||||||
|
|
||||||
CHECK(JS::Evaluate(cx, scopeChain, opts.setFileAndLine(__FILE__, __LINE__),
|
CHECK(JS::Evaluate(cx, envChain, opts.setFileAndLine(__FILE__, __LINE__),
|
||||||
srcBuf, &retval));
|
srcBuf, &retval));
|
||||||
|
|
||||||
bool hasProp = true;
|
bool hasProp = true;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "jit/Ion.h" // js::jit::IsIonEnabled
|
#include "jit/Ion.h" // js::jit::IsIonEnabled
|
||||||
#include "js/CallAndConstruct.h" // JS::CallFunction
|
#include "js/CallAndConstruct.h" // JS::CallFunction
|
||||||
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
|
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/GlobalObject.h" // JS_NewGlobalObject
|
#include "js/GlobalObject.h" // JS_NewGlobalObject
|
||||||
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
||||||
#include "jsapi-tests/tests.h"
|
#include "jsapi-tests/tests.h"
|
||||||
@@ -69,9 +70,9 @@ bool testPreserveJitCode(bool preserveJitCode, unsigned remainingIonScripts) {
|
|||||||
options.setFileAndLine(__FILE__, 1);
|
options.setFileAndLine(__FILE__, 1);
|
||||||
|
|
||||||
JS::RootedFunction fun(cx);
|
JS::RootedFunction fun(cx);
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, options, "f", 0, nullptr,
|
fun =
|
||||||
srcBuf);
|
JS::CompileFunction(cx, emptyEnvChain, options, "f", 0, nullptr, srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
|
|
||||||
RootedValue value(cx);
|
RootedValue value(cx);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
|
#include "mozilla/Utf8.h" // mozilla::Utf8Unit
|
||||||
|
|
||||||
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction, JS::Evaluate
|
#include "js/CompilationAndEvaluation.h" // JS::CompileFunction, JS::Evaluate
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/GlobalObject.h" // JS_NewGlobalObject
|
#include "js/GlobalObject.h" // JS_NewGlobalObject
|
||||||
#include "js/MemoryFunctions.h"
|
#include "js/MemoryFunctions.h"
|
||||||
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
||||||
@@ -41,13 +42,13 @@ BEGIN_TEST(testBug795104) {
|
|||||||
CHECK(JS::Evaluate(cx, opts, srcBuf, &unused));
|
CHECK(JS::Evaluate(cx, opts, srcBuf, &unused));
|
||||||
|
|
||||||
JS::RootedFunction fun(cx);
|
JS::RootedFunction fun(cx);
|
||||||
JS::RootedObjectVector emptyScopeChain(cx);
|
JS::EnvironmentChain emptyEnvChain(cx, JS::SupportUnscopables::No);
|
||||||
|
|
||||||
// But when compiling a function we don't want to use no-rval
|
// But when compiling a function we don't want to use no-rval
|
||||||
// mode, since it's not supported for functions.
|
// mode, since it's not supported for functions.
|
||||||
opts.setNoScriptRval(false);
|
opts.setNoScriptRval(false);
|
||||||
|
|
||||||
fun = JS::CompileFunction(cx, emptyScopeChain, opts, "f", 0, nullptr, srcBuf);
|
fun = JS::CompileFunction(cx, emptyEnvChain, opts, "f", 0, nullptr, srcBuf);
|
||||||
CHECK(fun);
|
CHECK(fun);
|
||||||
|
|
||||||
JS_free(cx, s);
|
JS_free(cx, s);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "frontend/CompilationStencil.h"
|
#include "frontend/CompilationStencil.h"
|
||||||
#include "js/CompilationAndEvaluation.h"
|
#include "js/CompilationAndEvaluation.h"
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/experimental/CompileScript.h"
|
#include "js/experimental/CompileScript.h"
|
||||||
#include "js/experimental/JSStencil.h"
|
#include "js/experimental/JSStencil.h"
|
||||||
#include "js/Modules.h"
|
#include "js/Modules.h"
|
||||||
@@ -136,11 +137,11 @@ BEGIN_TEST(testStencil_NonSyntactic) {
|
|||||||
CHECK(obj);
|
CHECK(obj);
|
||||||
CHECK(JS_SetProperty(cx, obj, "x", val));
|
CHECK(JS_SetProperty(cx, obj, "x", val));
|
||||||
|
|
||||||
JS::RootedObjectVector chain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No);
|
||||||
CHECK(chain.append(obj));
|
CHECK(envChain.append(obj));
|
||||||
|
|
||||||
JS::RootedValue rval(cx);
|
JS::RootedValue rval(cx);
|
||||||
CHECK(JS_ExecuteScript(cx, chain, script, &rval));
|
CHECK(JS_ExecuteScript(cx, envChain, script, &rval));
|
||||||
CHECK(rval.isNumber() && rval.toNumber() == 42);
|
CHECK(rval.isNumber() && rval.toNumber() == 42);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -136,6 +136,7 @@ EXPORTS.js += [
|
|||||||
"../public/Conversions.h",
|
"../public/Conversions.h",
|
||||||
"../public/Date.h",
|
"../public/Date.h",
|
||||||
"../public/Debug.h",
|
"../public/Debug.h",
|
||||||
|
"../public/EnvironmentChain.h",
|
||||||
"../public/Equality.h",
|
"../public/Equality.h",
|
||||||
"../public/ErrorInterceptor.h",
|
"../public/ErrorInterceptor.h",
|
||||||
"../public/ErrorReport.h",
|
"../public/ErrorReport.h",
|
||||||
|
|||||||
@@ -125,6 +125,7 @@
|
|||||||
#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions, JS::CompileOptions, JS::OwningCompileOptions, JS::DecodeOptions, JS::InstantiateOptions
|
#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions, JS::CompileOptions, JS::OwningCompileOptions, JS::DecodeOptions, JS::InstantiateOptions
|
||||||
#include "js/ContextOptions.h" // JS::ContextOptions{,Ref}
|
#include "js/ContextOptions.h" // JS::ContextOptions{,Ref}
|
||||||
#include "js/Debug.h" // JS::dbg::ShouldAvoidSideEffects, JS::ExecutionTrace
|
#include "js/Debug.h" // JS::dbg::ShouldAvoidSideEffects, JS::ExecutionTrace
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/Equality.h" // JS::SameValue
|
#include "js/Equality.h" // JS::SameValue
|
||||||
#include "js/ErrorReport.h" // JS::PrintError
|
#include "js/ErrorReport.h" // JS::PrintError
|
||||||
#include "js/Exception.h" // JS::StealPendingExceptionStack
|
#include "js/Exception.h" // JS::StealPendingExceptionStack
|
||||||
@@ -2693,7 +2694,7 @@ static bool Evaluate(JSContext* cx, unsigned argc, Value* vp) {
|
|||||||
bool saveIncrementalBytecode = false;
|
bool saveIncrementalBytecode = false;
|
||||||
bool execute = true;
|
bool execute = true;
|
||||||
bool assertEqBytecode = false;
|
bool assertEqBytecode = false;
|
||||||
JS::RootedObjectVector envChain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No);
|
||||||
RootedObject callerGlobal(cx, cx->global());
|
RootedObject callerGlobal(cx, cx->global());
|
||||||
|
|
||||||
options.setIntroductionType("js shell evaluate")
|
options.setIntroductionType("js shell evaluate")
|
||||||
@@ -2781,6 +2782,13 @@ static bool Evaluate(JSContext* cx, unsigned argc, Value* vp) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!JS_GetProperty(cx, opts, "supportUnscopables", &v)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!v.isUndefined()) {
|
||||||
|
envChain.setSupportUnscopables(JS::SupportUnscopables(ToBoolean(v)));
|
||||||
|
}
|
||||||
|
|
||||||
// We cannot load or save the bytecode if we have no object where the
|
// We cannot load or save the bytecode if we have no object where the
|
||||||
// bytecode cache is stored.
|
// bytecode cache is stored.
|
||||||
if (loadBytecode || saveIncrementalBytecode) {
|
if (loadBytecode || saveIncrementalBytecode) {
|
||||||
@@ -2796,7 +2804,7 @@ static bool Evaluate(JSContext* cx, unsigned argc, Value* vp) {
|
|||||||
// Wrap the envChainObject list into target realm.
|
// Wrap the envChainObject list into target realm.
|
||||||
JSAutoRealm ar(cx, global);
|
JSAutoRealm ar(cx, global);
|
||||||
for (size_t i = 0; i < envChain.length(); ++i) {
|
for (size_t i = 0; i < envChain.length(); ++i) {
|
||||||
if (!JS_WrapObject(cx, envChain[i])) {
|
if (!JS_WrapObject(cx, envChain.chain()[i])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9746,6 +9754,8 @@ static const JSFunctionSpecWithHelp shell_functions[] = {
|
|||||||
" envChainObject: object to put on the scope chain, with its fields added\n"
|
" envChainObject: object to put on the scope chain, with its fields added\n"
|
||||||
" as var bindings, akin to how elements are added to the environment in\n"
|
" as var bindings, akin to how elements are added to the environment in\n"
|
||||||
" event handlers in Gecko.\n"
|
" event handlers in Gecko.\n"
|
||||||
|
" supportUnscopables: if true, support Symbol.unscopables lookups for\n"
|
||||||
|
" envChainObject, similar to (syntactic) with-statements.\n"
|
||||||
),
|
),
|
||||||
|
|
||||||
JS_FN_HELP("run", Run, 1, 0,
|
JS_FN_HELP("run", Run, 1, 0,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "frontend/Parser.h" // frontend::Parser, frontend::ParseGoal
|
#include "frontend/Parser.h" // frontend::Parser, frontend::ParseGoal
|
||||||
#include "js/CharacterEncoding.h" // JS::UTF8Chars, JS::ConstUTF8CharsZ, JS::UTF8CharsToNewTwoByteCharsZ
|
#include "js/CharacterEncoding.h" // JS::UTF8Chars, JS::ConstUTF8CharsZ, JS::UTF8CharsToNewTwoByteCharsZ
|
||||||
#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
|
#include "js/ColumnNumber.h" // JS::ColumnNumberOneOrigin
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/experimental/JSStencil.h" // JS::Stencil
|
#include "js/experimental/JSStencil.h" // JS::Stencil
|
||||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||||
#include "js/RootingAPI.h" // JS::Rooted
|
#include "js/RootingAPI.h" // JS::Rooted
|
||||||
@@ -299,7 +300,7 @@ class FunctionCompiler {
|
|||||||
return funStr_.append(srcBuf.get(), srcBuf.length());
|
return funStr_.append(srcBuf.get(), srcBuf.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
JSFunction* finish(HandleObjectVector envChain,
|
JSFunction* finish(const JS::EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& optionsArg) {
|
const ReadOnlyCompileOptions& optionsArg) {
|
||||||
using js::frontend::FunctionSyntaxKind;
|
using js::frontend::FunctionSyntaxKind;
|
||||||
|
|
||||||
@@ -381,7 +382,7 @@ class FunctionCompiler {
|
|||||||
};
|
};
|
||||||
|
|
||||||
JS_PUBLIC_API JSFunction* JS::CompileFunction(
|
JS_PUBLIC_API JSFunction* JS::CompileFunction(
|
||||||
JSContext* cx, HandleObjectVector envChain,
|
JSContext* cx, const EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
||||||
const char* const* argnames, SourceText<char16_t>& srcBuf) {
|
const char* const* argnames, SourceText<char16_t>& srcBuf) {
|
||||||
ManualReportFrontendContext fc(cx);
|
ManualReportFrontendContext fc(cx);
|
||||||
@@ -397,7 +398,7 @@ JS_PUBLIC_API JSFunction* JS::CompileFunction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API JSFunction* JS::CompileFunction(
|
JS_PUBLIC_API JSFunction* JS::CompileFunction(
|
||||||
JSContext* cx, HandleObjectVector envChain,
|
JSContext* cx, const EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
||||||
const char* const* argnames, SourceText<Utf8Unit>& srcBuf) {
|
const char* const* argnames, SourceText<Utf8Unit>& srcBuf) {
|
||||||
ManualReportFrontendContext fc(cx);
|
ManualReportFrontendContext fc(cx);
|
||||||
@@ -413,7 +414,7 @@ JS_PUBLIC_API JSFunction* JS::CompileFunction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API JSFunction* JS::CompileFunctionUtf8(
|
JS_PUBLIC_API JSFunction* JS::CompileFunctionUtf8(
|
||||||
JSContext* cx, HandleObjectVector envChain,
|
JSContext* cx, const EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
const ReadOnlyCompileOptions& options, const char* name, unsigned nargs,
|
||||||
const char* const* argnames, const char* bytes, size_t length) {
|
const char* const* argnames, const char* bytes, size_t length) {
|
||||||
SourceText<Utf8Unit> srcBuf;
|
SourceText<Utf8Unit> srcBuf;
|
||||||
@@ -495,7 +496,7 @@ MOZ_NEVER_INLINE static bool ExecuteScript(JSContext* cx, HandleObject envChain,
|
|||||||
return Execute(cx, script, envChain, rval);
|
return Execute(cx, script, envChain, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ExecuteScript(JSContext* cx, HandleObjectVector envChain,
|
static bool ExecuteScript(JSContext* cx, const JS::EnvironmentChain& envChain,
|
||||||
HandleScript script, MutableHandleValue rval) {
|
HandleScript script, MutableHandleValue rval) {
|
||||||
RootedObject env(cx, CreateNonSyntacticEnvironmentChain(cx, envChain));
|
RootedObject env(cx, CreateNonSyntacticEnvironmentChain(cx, envChain));
|
||||||
if (!env) {
|
if (!env) {
|
||||||
@@ -520,13 +521,14 @@ MOZ_NEVER_INLINE JS_PUBLIC_API bool JS_ExecuteScript(JSContext* cx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
MOZ_NEVER_INLINE JS_PUBLIC_API bool JS_ExecuteScript(
|
MOZ_NEVER_INLINE JS_PUBLIC_API bool JS_ExecuteScript(
|
||||||
JSContext* cx, HandleObjectVector envChain, HandleScript scriptArg,
|
JSContext* cx, const JS::EnvironmentChain& envChain, HandleScript scriptArg,
|
||||||
MutableHandleValue rval) {
|
MutableHandleValue rval) {
|
||||||
return ExecuteScript(cx, envChain, scriptArg, rval);
|
return ExecuteScript(cx, envChain, scriptArg, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_NEVER_INLINE JS_PUBLIC_API bool JS_ExecuteScript(
|
MOZ_NEVER_INLINE JS_PUBLIC_API bool JS_ExecuteScript(
|
||||||
JSContext* cx, HandleObjectVector envChain, HandleScript scriptArg) {
|
JSContext* cx, const JS::EnvironmentChain& envChain,
|
||||||
|
HandleScript scriptArg) {
|
||||||
RootedValue rval(cx);
|
RootedValue rval(cx);
|
||||||
return ExecuteScript(cx, envChain, scriptArg, &rval);
|
return ExecuteScript(cx, envChain, scriptArg, &rval);
|
||||||
}
|
}
|
||||||
@@ -576,7 +578,7 @@ JS_PUBLIC_API bool JS::Evaluate(JSContext* cx,
|
|||||||
srcBuf, rval);
|
srcBuf, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API bool JS::Evaluate(JSContext* cx, HandleObjectVector envChain,
|
JS_PUBLIC_API bool JS::Evaluate(JSContext* cx, const EnvironmentChain& envChain,
|
||||||
const ReadOnlyCompileOptions& options,
|
const ReadOnlyCompileOptions& options,
|
||||||
SourceText<char16_t>& srcBuf,
|
SourceText<char16_t>& srcBuf,
|
||||||
MutableHandleValue rval) {
|
MutableHandleValue rval) {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
#include "builtin/Array.h"
|
#include "builtin/Array.h"
|
||||||
#include "builtin/ModuleObject.h"
|
#include "builtin/ModuleObject.h"
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/Exception.h"
|
#include "js/Exception.h"
|
||||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||||
#include "js/friend/StackLimits.h" // js::AutoCheckRecursionLimit
|
#include "js/friend/StackLimits.h" // js::AutoCheckRecursionLimit
|
||||||
@@ -717,10 +718,9 @@ JSObject* js::GetThisObject(JSObject* obj) {
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
WithEnvironmentObject* WithEnvironmentObject::create(JSContext* cx,
|
WithEnvironmentObject* WithEnvironmentObject::create(
|
||||||
HandleObject object,
|
JSContext* cx, HandleObject object, HandleObject enclosing,
|
||||||
HandleObject enclosing,
|
Handle<WithScope*> scope, JS::SupportUnscopables supportUnscopables) {
|
||||||
Handle<WithScope*> scope) {
|
|
||||||
Rooted<SharedShape*> shape(cx,
|
Rooted<SharedShape*> shape(cx,
|
||||||
EmptyEnvironmentShape<WithEnvironmentObject>(cx));
|
EmptyEnvironmentShape<WithEnvironmentObject>(cx));
|
||||||
if (!shape) {
|
if (!shape) {
|
||||||
@@ -738,17 +738,22 @@ WithEnvironmentObject* WithEnvironmentObject::create(JSContext* cx,
|
|||||||
obj->initReservedSlot(OBJECT_SLOT, ObjectValue(*object));
|
obj->initReservedSlot(OBJECT_SLOT, ObjectValue(*object));
|
||||||
obj->initReservedSlot(THIS_SLOT, ObjectValue(*thisObj));
|
obj->initReservedSlot(THIS_SLOT, ObjectValue(*thisObj));
|
||||||
if (scope) {
|
if (scope) {
|
||||||
obj->initReservedSlot(SCOPE_SLOT, PrivateGCThingValue(scope));
|
MOZ_ASSERT(supportUnscopables == JS::SupportUnscopables::Yes,
|
||||||
|
"with-statements must support Symbol.unscopables");
|
||||||
|
obj->initReservedSlot(SCOPE_OR_SUPPORT_UNSCOPABLES_SLOT,
|
||||||
|
PrivateGCThingValue(scope));
|
||||||
} else {
|
} else {
|
||||||
obj->initReservedSlot(SCOPE_SLOT, NullValue());
|
Value v = BooleanValue(supportUnscopables == JS::SupportUnscopables::Yes);
|
||||||
|
obj->initReservedSlot(SCOPE_OR_SUPPORT_UNSCOPABLES_SLOT, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
WithEnvironmentObject* WithEnvironmentObject::createNonSyntactic(
|
WithEnvironmentObject* WithEnvironmentObject::createNonSyntactic(
|
||||||
JSContext* cx, HandleObject object, HandleObject enclosing) {
|
JSContext* cx, HandleObject object, HandleObject enclosing,
|
||||||
return create(cx, object, enclosing, nullptr);
|
JS::SupportUnscopables supportUnscopables) {
|
||||||
|
return create(cx, object, enclosing, nullptr, supportUnscopables);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool IsUnscopableDotName(JSContext* cx, HandleId id) {
|
static inline bool IsUnscopableDotName(JSContext* cx, HandleId id) {
|
||||||
@@ -811,8 +816,9 @@ static bool with_LookupProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (propp->isFound()) {
|
if (propp->isFound()) {
|
||||||
bool scopable;
|
bool scopable = true;
|
||||||
if (!CheckUnscopables(cx, actual, id, &scopable)) {
|
if (obj->as<WithEnvironmentObject>().supportUnscopables() &&
|
||||||
|
!CheckUnscopables(cx, actual, id, &scopable)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!scopable) {
|
if (!scopable) {
|
||||||
@@ -840,7 +846,7 @@ static bool with_HasProperty(JSContext* cx, HandleObject obj, HandleId id,
|
|||||||
if (!HasProperty(cx, actual, id, foundp)) {
|
if (!HasProperty(cx, actual, id, foundp)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!*foundp) {
|
if (!*foundp || !obj->as<WithEnvironmentObject>().supportUnscopables()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -938,7 +944,7 @@ const JSClass NonSyntacticVariablesObject::class_ = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NonSyntacticLexicalEnvironmentObject* js::CreateNonSyntacticEnvironmentChain(
|
NonSyntacticLexicalEnvironmentObject* js::CreateNonSyntacticEnvironmentChain(
|
||||||
JSContext* cx, HandleObjectVector envChain) {
|
JSContext* cx, const JS::EnvironmentChain& envChain) {
|
||||||
// Callers are responsible for segregating the NonSyntactic case from simple
|
// Callers are responsible for segregating the NonSyntactic case from simple
|
||||||
// compilation cases.
|
// compilation cases.
|
||||||
MOZ_RELEASE_ASSERT(!envChain.empty());
|
MOZ_RELEASE_ASSERT(!envChain.empty());
|
||||||
@@ -2437,9 +2443,12 @@ class DebugEnvironmentProxyHandler : public NurseryAllocableProxyHandler {
|
|||||||
|
|
||||||
if (isWith) {
|
if (isWith) {
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
|
bool supportUnscopables =
|
||||||
|
env->as<WithEnvironmentObject>().supportUnscopables();
|
||||||
for (size_t i = 0; i < props.length(); i++) {
|
for (size_t i = 0; i < props.length(); i++) {
|
||||||
bool inScope;
|
bool inScope = true;
|
||||||
if (!CheckUnscopables(cx, env, props[i], &inScope)) {
|
if (supportUnscopables &&
|
||||||
|
!CheckUnscopables(cx, env, props[i], &inScope)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (inScope) {
|
if (inScope) {
|
||||||
@@ -3429,13 +3438,14 @@ JSObject* js::GetDebugEnvironmentForGlobalLexicalEnvironment(JSContext* cx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
WithEnvironmentObject* js::CreateObjectsForEnvironmentChain(
|
WithEnvironmentObject* js::CreateObjectsForEnvironmentChain(
|
||||||
JSContext* cx, HandleObjectVector chain, HandleObject terminatingEnv) {
|
JSContext* cx, const JS::EnvironmentChain& chain,
|
||||||
|
HandleObject terminatingEnv) {
|
||||||
MOZ_ASSERT(!chain.empty());
|
MOZ_ASSERT(!chain.empty());
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (size_t i = 0; i < chain.length(); ++i) {
|
for (size_t i = 0; i < chain.length(); ++i) {
|
||||||
cx->check(chain[i]);
|
cx->check(chain.chain()[i]);
|
||||||
MOZ_ASSERT(!chain[i]->isUnqualifiedVarObj());
|
MOZ_ASSERT(!chain.chain()[i]->isUnqualifiedVarObj());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -3444,8 +3454,8 @@ WithEnvironmentObject* js::CreateObjectsForEnvironmentChain(
|
|||||||
Rooted<WithEnvironmentObject*> withEnv(cx);
|
Rooted<WithEnvironmentObject*> withEnv(cx);
|
||||||
RootedObject enclosingEnv(cx, terminatingEnv);
|
RootedObject enclosingEnv(cx, terminatingEnv);
|
||||||
for (size_t i = chain.length(); i > 0;) {
|
for (size_t i = chain.length(); i > 0;) {
|
||||||
withEnv =
|
withEnv = WithEnvironmentObject::createNonSyntactic(
|
||||||
WithEnvironmentObject::createNonSyntactic(cx, chain[--i], enclosingEnv);
|
cx, chain.chain()[--i], enclosingEnv, chain.supportUnscopables());
|
||||||
if (!withEnv) {
|
if (!withEnv) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -3470,14 +3480,24 @@ JSObject* WithEnvironmentObject::withThis() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool WithEnvironmentObject::isSyntactic() const {
|
bool WithEnvironmentObject::isSyntactic() const {
|
||||||
Value v = getReservedSlot(SCOPE_SLOT);
|
Value v = getReservedSlot(SCOPE_OR_SUPPORT_UNSCOPABLES_SLOT);
|
||||||
MOZ_ASSERT(v.isPrivateGCThing() || v.isNull());
|
MOZ_ASSERT(v.isPrivateGCThing() || v.isBoolean());
|
||||||
return v.isPrivateGCThing();
|
return v.isPrivateGCThing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WithEnvironmentObject::supportUnscopables() const {
|
||||||
|
if (isSyntactic()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Value v = getReservedSlot(SCOPE_OR_SUPPORT_UNSCOPABLES_SLOT);
|
||||||
|
MOZ_ASSERT(v.isBoolean());
|
||||||
|
return v.isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
WithScope& WithEnvironmentObject::scope() const {
|
WithScope& WithEnvironmentObject::scope() const {
|
||||||
MOZ_ASSERT(isSyntactic());
|
MOZ_ASSERT(isSyntactic());
|
||||||
return *static_cast<WithScope*>(getReservedSlot(SCOPE_SLOT).toGCThing());
|
Value v = getReservedSlot(SCOPE_OR_SUPPORT_UNSCOPABLES_SLOT);
|
||||||
|
return *static_cast<WithScope*>(v.toGCThing());
|
||||||
}
|
}
|
||||||
|
|
||||||
ModuleEnvironmentObject* js::GetModuleEnvironmentForScript(JSScript* script) {
|
ModuleEnvironmentObject* js::GetModuleEnvironmentForScript(JSScript* script) {
|
||||||
|
|||||||
@@ -20,6 +20,11 @@
|
|||||||
#include "vm/Scope.h"
|
#include "vm/Scope.h"
|
||||||
#include "vm/ScopeKind.h" // ScopeKind
|
#include "vm/ScopeKind.h" // ScopeKind
|
||||||
|
|
||||||
|
namespace JS {
|
||||||
|
class JS_PUBLIC_API EnvironmentChain;
|
||||||
|
enum class SupportUnscopables : bool;
|
||||||
|
}; // namespace JS
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
class AbstractGeneratorObject;
|
class AbstractGeneratorObject;
|
||||||
@@ -175,6 +180,11 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
*
|
*
|
||||||
* Does not hold 'let' or 'const' bindings.
|
* Does not hold 'let' or 'const' bindings.
|
||||||
*
|
*
|
||||||
|
* The embedding can specify whether these non-syntactic WithEnvironment
|
||||||
|
* objects support Symbol.unscopables similar to syntactic 'with' statements
|
||||||
|
* in JS. In Firefox, we support Symbol.unscopables only for DOM event
|
||||||
|
* handlers because this is required by the spec.
|
||||||
|
*
|
||||||
* 2. NonSyntacticVariablesObject
|
* 2. NonSyntacticVariablesObject
|
||||||
*
|
*
|
||||||
* When the embedding wants qualified 'var' bindings and unqualified
|
* When the embedding wants qualified 'var' bindings and unqualified
|
||||||
@@ -234,7 +244,8 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* GlobalLexicalEnvironmentObject[this=global]
|
* GlobalLexicalEnvironmentObject[this=global]
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping target (qualified 'var's)
|
* WithEnvironmentObject [SupportUnscopables=No] wrapping target
|
||||||
|
* (qualified 'var's)
|
||||||
* |
|
* |
|
||||||
* NonSyntacticLexicalEnvironmentObject[this=target] (lexical vars)
|
* NonSyntacticLexicalEnvironmentObject[this=target] (lexical vars)
|
||||||
*
|
*
|
||||||
@@ -263,7 +274,8 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* NonSyntacticLexicalEnvironmentObject[this=nsvo]
|
* NonSyntacticLexicalEnvironmentObject[this=nsvo]
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping target (qualified 'var's)
|
* WithEnvironmentObject [SupportUnscopables=No] wrapping target
|
||||||
|
* (qualified 'var's)
|
||||||
* |
|
* |
|
||||||
* NonSyntacticLexicalEnvironmentObject[this=target] (lexical vars)
|
* NonSyntacticLexicalEnvironmentObject[this=target] (lexical vars)
|
||||||
*
|
*
|
||||||
@@ -298,7 +310,7 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* NonSyntacticVariablesObject (qualified 'var's and unqualified names)
|
* NonSyntacticVariablesObject (qualified 'var's and unqualified names)
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping messageManager
|
* WithEnvironmentObject [SupportUnscopables=No] wrapping messageManager
|
||||||
* |
|
* |
|
||||||
* NonSyntacticLexicalEnvironmentObject[this=messageManager] (lexical vars)
|
* NonSyntacticLexicalEnvironmentObject[this=messageManager] (lexical vars)
|
||||||
*
|
*
|
||||||
@@ -315,7 +327,8 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* GlobalLexicalEnvironmentObject[this=global]
|
* GlobalLexicalEnvironmentObject[this=global]
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping messageManager (qualified 'var's)
|
* WithEnvironmentObject [SupportUnscopables=No] wrapping messageManager
|
||||||
|
* (qualified 'var's)
|
||||||
* |
|
* |
|
||||||
* NonSyntacticLexicalEnvironmentObject[this=messageManager] (lexical vars)
|
* NonSyntacticLexicalEnvironmentObject[this=messageManager] (lexical vars)
|
||||||
*
|
*
|
||||||
@@ -334,13 +347,13 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* GlobalLexicalEnvironmentObject[this=global]
|
* GlobalLexicalEnvironmentObject[this=global]
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping eN
|
* WithEnvironmentObject [SupportUnscopables=Yes] wrapping eN
|
||||||
* |
|
* |
|
||||||
* ...
|
* ...
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping e1
|
* WithEnvironmentObject [SupportUnscopables=Yes] wrapping e1
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping e0
|
* WithEnvironmentObject [SupportUnscopables=Yes] wrapping e0
|
||||||
* |
|
* |
|
||||||
* NonSyntacticLexicalEnvironmentObject [this=*unused*]
|
* NonSyntacticLexicalEnvironmentObject [this=*unused*]
|
||||||
*
|
*
|
||||||
@@ -355,9 +368,9 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* ...
|
* ...
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping e1
|
* WithEnvironmentObject [SupportUnscopables=Yes] wrapping e1
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping e0
|
* WithEnvironmentObject [SupportUnscopables=Yes] wrapping e0
|
||||||
* |
|
* |
|
||||||
* NonSyntacticLexicalEnvironmentObject [this=*unused*]
|
* NonSyntacticLexicalEnvironmentObject [this=*unused*]
|
||||||
* |
|
* |
|
||||||
@@ -383,7 +396,8 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* [DebugProxy] CallObject (qualified 'var's)
|
* [DebugProxy] CallObject (qualified 'var's)
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping bindings (conflicting 'var's and names)
|
* WithEnvironmentObject [SupportUnscopables=No] wrapping bindings
|
||||||
|
* (conflicting 'var's and names)
|
||||||
*
|
*
|
||||||
* If the script has direct eval, BlockLexicalEnvironmentObject is created for
|
* If the script has direct eval, BlockLexicalEnvironmentObject is created for
|
||||||
* it:
|
* it:
|
||||||
@@ -394,7 +408,8 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* [DebugProxy] CallObject (qualified 'var's)
|
* [DebugProxy] CallObject (qualified 'var's)
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping bindings (conflicting 'var's and names)
|
* WithEnvironmentObject [SupportUnscopables=No] wrapping bindings
|
||||||
|
* (conflicting 'var's and names)
|
||||||
* |
|
* |
|
||||||
* BlockLexicalEnvironmentObject (lexical vars, and conflicting lexical vars)
|
* BlockLexicalEnvironmentObject (lexical vars, and conflicting lexical vars)
|
||||||
*
|
*
|
||||||
@@ -415,7 +430,8 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* GlobalLexicalEnvironmentObject[this=global] (lexical vars)
|
* GlobalLexicalEnvironmentObject[this=global] (lexical vars)
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping object with not-conflicting bindings
|
* WithEnvironmentObject [SupportUnscopables=No] wrapping object with
|
||||||
|
* not-conflicting bindings
|
||||||
*
|
*
|
||||||
* If `options.useInnerBindings` is true, all bindings are stored into the
|
* If `options.useInnerBindings` is true, all bindings are stored into the
|
||||||
* bindings object wrapped by WithEnvironmentObject, and they shadow globals
|
* bindings object wrapped by WithEnvironmentObject, and they shadow globals
|
||||||
@@ -424,7 +440,8 @@ extern PropertyName* EnvironmentCoordinateNameSlow(JSScript* script,
|
|||||||
* |
|
* |
|
||||||
* GlobalLexicalEnvironmentObject[this=global] (lexical vars)
|
* GlobalLexicalEnvironmentObject[this=global] (lexical vars)
|
||||||
* |
|
* |
|
||||||
* WithEnvironmentObject wrapping object with all bindings
|
* WithEnvironmentObject [SupportUnscopables=No] wrapping object with all
|
||||||
|
* bindings
|
||||||
*
|
*
|
||||||
* NOTE: If `options.useInnerBindings` is true, and if lexical variable names
|
* NOTE: If `options.useInnerBindings` is true, and if lexical variable names
|
||||||
* conflict with the bindings object's properties, the write on them
|
* conflict with the bindings object's properties, the write on them
|
||||||
@@ -982,13 +999,16 @@ class NonSyntacticVariablesObject : public EnvironmentObject {
|
|||||||
};
|
};
|
||||||
|
|
||||||
NonSyntacticLexicalEnvironmentObject* CreateNonSyntacticEnvironmentChain(
|
NonSyntacticLexicalEnvironmentObject* CreateNonSyntacticEnvironmentChain(
|
||||||
JSContext* cx, JS::HandleObjectVector envChain);
|
JSContext* cx, const JS::EnvironmentChain& envChain);
|
||||||
|
|
||||||
// With environment objects on the run-time environment chain.
|
// With environment objects on the run-time environment chain.
|
||||||
class WithEnvironmentObject : public EnvironmentObject {
|
class WithEnvironmentObject : public EnvironmentObject {
|
||||||
static constexpr uint32_t OBJECT_SLOT = 1;
|
static constexpr uint32_t OBJECT_SLOT = 1;
|
||||||
static constexpr uint32_t THIS_SLOT = 2;
|
static constexpr uint32_t THIS_SLOT = 2;
|
||||||
static constexpr uint32_t SCOPE_SLOT = 3;
|
// For syntactic with-environments this slot stores the js::Scope*.
|
||||||
|
// For non-syntactic with-environments it stores a boolean indicating whether
|
||||||
|
// we need to look up and use Symbol.unscopables.
|
||||||
|
static constexpr uint32_t SCOPE_OR_SUPPORT_UNSCOPABLES_SLOT = 3;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const JSClass class_;
|
static const JSClass class_;
|
||||||
@@ -996,12 +1016,12 @@ class WithEnvironmentObject : public EnvironmentObject {
|
|||||||
static constexpr uint32_t RESERVED_SLOTS = 4;
|
static constexpr uint32_t RESERVED_SLOTS = 4;
|
||||||
static constexpr ObjectFlags OBJECT_FLAGS = {};
|
static constexpr ObjectFlags OBJECT_FLAGS = {};
|
||||||
|
|
||||||
static WithEnvironmentObject* create(JSContext* cx, HandleObject object,
|
static WithEnvironmentObject* create(
|
||||||
HandleObject enclosing,
|
JSContext* cx, HandleObject object, HandleObject enclosing,
|
||||||
Handle<WithScope*> scope);
|
Handle<WithScope*> scope, JS::SupportUnscopables supportUnscopables);
|
||||||
static WithEnvironmentObject* createNonSyntactic(JSContext* cx,
|
static WithEnvironmentObject* createNonSyntactic(
|
||||||
HandleObject object,
|
JSContext* cx, HandleObject object, HandleObject enclosing,
|
||||||
HandleObject enclosing);
|
JS::SupportUnscopables supportUnscopables);
|
||||||
|
|
||||||
/* Return the 'o' in 'with (o)'. */
|
/* Return the 'o' in 'with (o)'. */
|
||||||
JSObject& object() const;
|
JSObject& object() const;
|
||||||
@@ -1017,6 +1037,10 @@ class WithEnvironmentObject : public EnvironmentObject {
|
|||||||
*/
|
*/
|
||||||
bool isSyntactic() const;
|
bool isSyntactic() const;
|
||||||
|
|
||||||
|
// Whether Symbol.unscopables must be supported for this with-environment.
|
||||||
|
// This always returns true for syntactic with-environments.
|
||||||
|
bool supportUnscopables() const;
|
||||||
|
|
||||||
// For syntactic with environment objects, the with scope.
|
// For syntactic with environment objects, the with scope.
|
||||||
WithScope& scope() const;
|
WithScope& scope() const;
|
||||||
|
|
||||||
@@ -1565,7 +1589,8 @@ inline bool IsFrameInitialEnvironment(AbstractFramePtr frame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
WithEnvironmentObject* CreateObjectsForEnvironmentChain(
|
WithEnvironmentObject* CreateObjectsForEnvironmentChain(
|
||||||
JSContext* cx, HandleObjectVector chain, HandleObject terminatingEnv);
|
JSContext* cx, const JS::EnvironmentChain& envChain,
|
||||||
|
HandleObject terminatingEnv);
|
||||||
|
|
||||||
ModuleObject* GetModuleObjectForScript(JSScript* script);
|
ModuleObject* GetModuleObjectForScript(JSScript* script);
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,8 @@ inline bool FetchName(JSContext* cx, HandleObject receiver, HandleObject holder,
|
|||||||
|
|
||||||
/* Take the slow path if shape was not found in a native object. */
|
/* Take the slow path if shape was not found in a native object. */
|
||||||
if (!receiver->is<NativeObject>() || !holder->is<NativeObject>() ||
|
if (!receiver->is<NativeObject>() || !holder->is<NativeObject>() ||
|
||||||
receiver->is<WithEnvironmentObject>()) {
|
(receiver->is<WithEnvironmentObject>() &&
|
||||||
|
receiver->as<WithEnvironmentObject>().supportUnscopables())) {
|
||||||
Rooted<jsid> id(cx, NameToId(name));
|
Rooted<jsid> id(cx, NameToId(name));
|
||||||
if (!GetProperty(cx, receiver, receiver, id, vp)) {
|
if (!GetProperty(cx, receiver, receiver, id, vp)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -108,8 +109,11 @@ inline bool FetchName(JSContext* cx, HandleObject receiver, HandleObject holder,
|
|||||||
/* Fast path for Object instance properties. */
|
/* Fast path for Object instance properties. */
|
||||||
vp.set(holder->as<NativeObject>().getSlot(propInfo.slot()));
|
vp.set(holder->as<NativeObject>().getSlot(propInfo.slot()));
|
||||||
} else {
|
} else {
|
||||||
|
// Unwrap 'with' environments for reasons given in
|
||||||
|
// GetNameBoundInEnvironment.
|
||||||
|
RootedObject normalized(cx, MaybeUnwrapWithEnvironment(receiver));
|
||||||
RootedId id(cx, NameToId(name));
|
RootedId id(cx, NameToId(name));
|
||||||
if (!NativeGetExistingProperty(cx, receiver, holder.as<NativeObject>(),
|
if (!NativeGetExistingProperty(cx, normalized, holder.as<NativeObject>(),
|
||||||
id, propInfo, vp)) {
|
id, propInfo, vp)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "jit/BaselineJIT.h"
|
#include "jit/BaselineJIT.h"
|
||||||
#include "jit/Jit.h"
|
#include "jit/Jit.h"
|
||||||
#include "jit/JitRuntime.h"
|
#include "jit/JitRuntime.h"
|
||||||
|
#include "js/EnvironmentChain.h" // JS::SupportUnscopables
|
||||||
#include "js/experimental/JitInfo.h" // JSJitInfo
|
#include "js/experimental/JitInfo.h" // JSJitInfo
|
||||||
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
#include "js/friend/ErrorMessages.h" // js::GetErrorMessage, JSMSG_*
|
||||||
#include "js/friend/StackLimits.h" // js::AutoCheckRecursionLimit
|
#include "js/friend/StackLimits.h" // js::AutoCheckRecursionLimit
|
||||||
@@ -1071,8 +1072,8 @@ bool js::EnterWithOperation(JSContext* cx, AbstractFramePtr frame,
|
|||||||
}
|
}
|
||||||
|
|
||||||
RootedObject envChain(cx, frame.environmentChain());
|
RootedObject envChain(cx, frame.environmentChain());
|
||||||
WithEnvironmentObject* withobj =
|
WithEnvironmentObject* withobj = WithEnvironmentObject::create(
|
||||||
WithEnvironmentObject::create(cx, obj, envChain, scope);
|
cx, obj, envChain, scope, JS::SupportUnscopables::Yes);
|
||||||
if (!withobj) {
|
if (!withobj) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "xpcprivate.h" // xpc::OptionsBase
|
#include "xpcprivate.h" // xpc::OptionsBase
|
||||||
#include "js/CompilationAndEvaluation.h" // JS::Compile
|
#include "js/CompilationAndEvaluation.h" // JS::Compile
|
||||||
#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions, JS::DecodeOptions
|
#include "js/CompileOptions.h" // JS::ReadOnlyCompileOptions, JS::DecodeOptions
|
||||||
|
#include "js/EnvironmentChain.h" // JS::EnvironmentChain
|
||||||
#include "js/friend/JSMEnvironment.h" // JS::ExecuteInJSMEnvironment, JS::IsJSMEnvironment
|
#include "js/friend/JSMEnvironment.h" // JS::ExecuteInJSMEnvironment, JS::IsJSMEnvironment
|
||||||
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
#include "js/SourceText.h" // JS::Source{Ownership,Text}
|
||||||
#include "js/Wrapper.h"
|
#include "js/Wrapper.h"
|
||||||
@@ -146,7 +147,7 @@ static bool EvalStencil(JSContext* cx, HandleObject targetObj,
|
|||||||
}
|
}
|
||||||
retval.setUndefined();
|
retval.setUndefined();
|
||||||
} else {
|
} else {
|
||||||
JS::RootedObjectVector envChain(cx);
|
JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No);
|
||||||
if (!envChain.append(targetObj)) {
|
if (!envChain.append(targetObj)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user