mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 10:00:54 +00:00
Bug 1181908. The CompileOptions constructor should properly copy the introducerFilename and isRunOnce state. r=luke
This commit is contained in:
parent
996744154e
commit
11d4b0065f
@ -99,6 +99,7 @@ using JS::NativeImpl;
|
||||
using JS::OwningCompileOptions;
|
||||
using JS::ReadOnlyCompileOptions;
|
||||
using JS::SourceBufferHolder;
|
||||
using JS::TransitiveCompileOptions;
|
||||
|
||||
using JS::Rooted;
|
||||
using JS::RootedFunction;
|
||||
|
@ -5767,13 +5767,13 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
||||
funbox->setMightAliasLocals(); // inherit mightAliasLocals from parent
|
||||
MOZ_ASSERT_IF(outersc->strict(), funbox->strictScript);
|
||||
|
||||
// Inherit most things (principals, version, etc) from the parent.
|
||||
// Inherit most things (principals, version, etc) from the
|
||||
// parent. Use default values for the rest.
|
||||
Rooted<JSScript*> parent(cx, script);
|
||||
CompileOptions options(cx, parser->options());
|
||||
options.setMutedErrors(parent->mutedErrors())
|
||||
.setNoScriptRval(false)
|
||||
.setForEval(false)
|
||||
.setVersion(parent->getVersion());
|
||||
MOZ_ASSERT(parent->getVersion() == parser->options().version);
|
||||
MOZ_ASSERT(parent->mutedErrors() == parser->options().mutedErrors());
|
||||
const TransitiveCompileOptions& transitiveOptions = parser->options();
|
||||
CompileOptions options(cx, transitiveOptions);
|
||||
|
||||
Rooted<JSObject*> enclosingScope(cx, enclosingStaticScope());
|
||||
Rooted<JSObject*> sourceObject(cx, script->sourceObject());
|
||||
|
@ -3813,18 +3813,13 @@ AutoFile::open(JSContext* cx, const char* filename)
|
||||
return true;
|
||||
}
|
||||
|
||||
JSObject * const JS::ReadOnlyCompileOptions::nullObjectPtr = nullptr;
|
||||
|
||||
void
|
||||
JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions& rhs)
|
||||
JS::TransitiveCompileOptions::copyPODTransitiveOptions(const TransitiveCompileOptions& rhs)
|
||||
{
|
||||
mutedErrors_ = rhs.mutedErrors_;
|
||||
version = rhs.version;
|
||||
versionSet = rhs.versionSet;
|
||||
utf8 = rhs.utf8;
|
||||
lineno = rhs.lineno;
|
||||
column = rhs.column;
|
||||
forEval = rhs.forEval;
|
||||
noScriptRval = rhs.noScriptRval;
|
||||
selfHostingMode = rhs.selfHostingMode;
|
||||
canLazilyParse = rhs.canLazilyParse;
|
||||
strictOption = rhs.strictOption;
|
||||
@ -3838,6 +3833,17 @@ JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions& rhs)
|
||||
introductionLineno = rhs.introductionLineno;
|
||||
introductionOffset = rhs.introductionOffset;
|
||||
hasIntroductionInfo = rhs.hasIntroductionInfo;
|
||||
};
|
||||
|
||||
void
|
||||
JS::ReadOnlyCompileOptions::copyPODOptions(const ReadOnlyCompileOptions& rhs)
|
||||
{
|
||||
copyPODTransitiveOptions(rhs);
|
||||
lineno = rhs.lineno;
|
||||
column = rhs.column;
|
||||
isRunOnce = rhs.isRunOnce;
|
||||
forEval = rhs.forEval;
|
||||
noScriptRval = rhs.noScriptRval;
|
||||
}
|
||||
|
||||
JS::OwningCompileOptions::OwningCompileOptions(JSContext* cx)
|
||||
@ -3862,7 +3868,6 @@ JS::OwningCompileOptions::copy(JSContext* cx, const ReadOnlyCompileOptions& rhs)
|
||||
{
|
||||
copyPODOptions(rhs);
|
||||
|
||||
setMutedErrors(rhs.mutedErrors());
|
||||
setElement(rhs.element());
|
||||
setElementAttributeName(rhs.elementAttributeName());
|
||||
setIntroductionScript(rhs.introductionScript());
|
||||
@ -4270,8 +4275,7 @@ CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
MOZ_ASSERT_IF(!enclosingDynamicScope->is<GlobalObject>(),
|
||||
HasNonSyntacticStaticScopeChain(enclosingStaticScope));
|
||||
|
||||
CompileOptions options(cx, optionsArg);
|
||||
if (!frontend::CompileFunctionBody(cx, fun, options, formals, srcBuf, enclosingStaticScope))
|
||||
if (!frontend::CompileFunctionBody(cx, fun, optionsArg, formals, srcBuf, enclosingStaticScope))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
107
js/src/jsapi.h
107
js/src/jsapi.h
@ -3384,10 +3384,20 @@ namespace JS {
|
||||
* it doesn't care who owns them, or what's keeping them alive. It does its own
|
||||
* addrefs/copies/tracing/etc.
|
||||
*
|
||||
* So, we have a class hierarchy that reflects these three use cases:
|
||||
* Furthermore, in some cases compile options are propagated from one entity to
|
||||
* another (e.g. from a scriipt to a function defined in that script). This
|
||||
* involves copying over some, but not all, of the options.
|
||||
*
|
||||
* - ReadOnlyCompileOptions is the common base class. It can be used by code
|
||||
* that simply needs to access options set elsewhere, like the compiler.
|
||||
* So, we have a class hierarchy that reflects these four use cases:
|
||||
*
|
||||
* - TransitiveCompileOptions is the common base class, representing options
|
||||
* that should get propagated from a script to functions defined in that
|
||||
* script. This is never instantiated directly.
|
||||
*
|
||||
* - ReadOnlyCompileOptions is the only subclass of TransitiveCompileOptions,
|
||||
* representing a full set of compile options. It can be used by code that
|
||||
* simply needs to access options set elsewhere, like the compiler. This,
|
||||
* again, is never instantiated directly.
|
||||
*
|
||||
* - The usual CompileOptions class must be stack-allocated, and holds
|
||||
* non-owning references to the filename, element, and so on. It's derived
|
||||
@ -3401,15 +3411,11 @@ namespace JS {
|
||||
/*
|
||||
* The common base class for the CompileOptions hierarchy.
|
||||
*
|
||||
* Use this in code that only needs to access compilation options created
|
||||
* elsewhere, like the compiler. Don't instantiate this class (the constructor
|
||||
* is protected anyway); instead, create instances only of the derived classes:
|
||||
* CompileOptions and OwningCompileOptions.
|
||||
* Use this in code that needs to propagate compile options from one compilation
|
||||
* unit to another.
|
||||
*/
|
||||
class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||
class JS_FRIEND_API(TransitiveCompileOptions)
|
||||
{
|
||||
friend class CompileOptions;
|
||||
|
||||
protected:
|
||||
// The Web Platform allows scripts to be loaded from arbitrary cross-origin
|
||||
// sources. This allows an attack by which a malicious website loads a
|
||||
@ -3431,7 +3437,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||
// is unusable until that's set to something more specific; the derived
|
||||
// classes' constructors take care of that, in ways appropriate to their
|
||||
// purpose.
|
||||
ReadOnlyCompileOptions()
|
||||
TransitiveCompileOptions()
|
||||
: mutedErrors_(false),
|
||||
filename_(nullptr),
|
||||
introducerFilename_(nullptr),
|
||||
@ -3439,11 +3445,6 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||
version(JSVERSION_UNKNOWN),
|
||||
versionSet(false),
|
||||
utf8(false),
|
||||
lineno(1),
|
||||
column(0),
|
||||
isRunOnce(false),
|
||||
forEval(false),
|
||||
noScriptRval(false),
|
||||
selfHostingMode(false),
|
||||
canLazilyParse(true),
|
||||
strictOption(false),
|
||||
@ -3461,7 +3462,7 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||
|
||||
// Set all POD options (those not requiring reference counts, copies,
|
||||
// rooting, or other hand-holding) to their values in |rhs|.
|
||||
void copyPODOptions(const ReadOnlyCompileOptions& rhs);
|
||||
void copyPODTransitiveOptions(const TransitiveCompileOptions& rhs);
|
||||
|
||||
public:
|
||||
// Read-only accessors for non-POD options. The proper way to set these
|
||||
@ -3478,12 +3479,6 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||
JSVersion version;
|
||||
bool versionSet;
|
||||
bool utf8;
|
||||
unsigned lineno;
|
||||
unsigned column;
|
||||
// isRunOnce only applies to non-function scripts.
|
||||
bool isRunOnce;
|
||||
bool forEval;
|
||||
bool noScriptRval;
|
||||
bool selfHostingMode;
|
||||
bool canLazilyParse;
|
||||
bool strictOption;
|
||||
@ -3502,7 +3497,55 @@ class JS_FRIEND_API(ReadOnlyCompileOptions)
|
||||
bool hasIntroductionInfo;
|
||||
|
||||
private:
|
||||
static JSObject * const nullObjectPtr;
|
||||
void operator=(const TransitiveCompileOptions&) = delete;
|
||||
};
|
||||
|
||||
/*
|
||||
* The class representing a full set of compile options.
|
||||
*
|
||||
* Use this in code that only needs to access compilation options created
|
||||
* elsewhere, like the compiler. Don't instantiate this class (the constructor
|
||||
* is protected anyway); instead, create instances only of the derived classes:
|
||||
* CompileOptions and OwningCompileOptions.
|
||||
*/
|
||||
class JS_FRIEND_API(ReadOnlyCompileOptions) : public TransitiveCompileOptions
|
||||
{
|
||||
friend class CompileOptions;
|
||||
|
||||
protected:
|
||||
ReadOnlyCompileOptions()
|
||||
: TransitiveCompileOptions(),
|
||||
lineno(1),
|
||||
column(0),
|
||||
isRunOnce(false),
|
||||
forEval(false),
|
||||
noScriptRval(false)
|
||||
{ }
|
||||
|
||||
// Set all POD options (those not requiring reference counts, copies,
|
||||
// rooting, or other hand-holding) to their values in |rhs|.
|
||||
void copyPODOptions(const ReadOnlyCompileOptions& rhs);
|
||||
|
||||
public:
|
||||
// Read-only accessors for non-POD options. The proper way to set these
|
||||
// depends on the derived type.
|
||||
bool mutedErrors() const { return mutedErrors_; }
|
||||
const char* filename() const { return filename_; }
|
||||
const char* introducerFilename() const { return introducerFilename_; }
|
||||
const char16_t* sourceMapURL() const { return sourceMapURL_; }
|
||||
virtual JSObject* element() const = 0;
|
||||
virtual JSString* elementAttributeName() const = 0;
|
||||
virtual JSScript* introductionScript() const = 0;
|
||||
|
||||
// POD options.
|
||||
unsigned lineno;
|
||||
unsigned column;
|
||||
// isRunOnce only applies to non-function scripts.
|
||||
bool isRunOnce;
|
||||
bool forEval;
|
||||
bool noScriptRval;
|
||||
|
||||
private:
|
||||
void operator=(const ReadOnlyCompileOptions&) = delete;
|
||||
};
|
||||
|
||||
@ -3617,8 +3660,22 @@ class MOZ_STACK_CLASS JS_FRIEND_API(CompileOptions) : public ReadOnlyCompileOpti
|
||||
{
|
||||
copyPODOptions(rhs);
|
||||
|
||||
mutedErrors_ = rhs.mutedErrors_;
|
||||
filename_ = rhs.filename();
|
||||
introducerFilename_ = rhs.introducerFilename();
|
||||
sourceMapURL_ = rhs.sourceMapURL();
|
||||
elementRoot = rhs.element();
|
||||
elementAttributeNameRoot = rhs.elementAttributeName();
|
||||
introductionScriptRoot = rhs.introductionScript();
|
||||
}
|
||||
|
||||
CompileOptions(js::ContextFriendFields* cx, const TransitiveCompileOptions& rhs)
|
||||
: ReadOnlyCompileOptions(), elementRoot(cx), elementAttributeNameRoot(cx),
|
||||
introductionScriptRoot(cx)
|
||||
{
|
||||
copyPODTransitiveOptions(rhs);
|
||||
|
||||
filename_ = rhs.filename();
|
||||
introducerFilename_ = rhs.introducerFilename();
|
||||
sourceMapURL_ = rhs.sourceMapURL();
|
||||
elementRoot = rhs.element();
|
||||
elementAttributeNameRoot = rhs.elementAttributeName();
|
||||
|
@ -37,6 +37,7 @@ class Rooted;
|
||||
class JS_FRIEND_API(CompileOptions);
|
||||
class JS_FRIEND_API(ReadOnlyCompileOptions);
|
||||
class JS_FRIEND_API(OwningCompileOptions);
|
||||
class JS_FRIEND_API(TransitiveCompileOptions);
|
||||
class JS_PUBLIC_API(CompartmentOptions);
|
||||
|
||||
class Value;
|
||||
|
Loading…
Reference in New Issue
Block a user