зеркало из https://github.com/mozilla/gecko-dev.git
Bug 540675: eviscerate JSStackFrame::callerVersion. (r=lw)
This commit is contained in:
Родитель
0f3cc3cd5f
Коммит
7473b7380d
|
@ -468,7 +468,7 @@ nsScriptLoader::ProcessScriptElement(nsIScriptElement *aElement)
|
|||
// We re-use our knowledge of the implementation to reuse
|
||||
// JSVERSION_HAS_XML as a safe version flag.
|
||||
// If version has JSVERSION_UNKNOWN (-1), then this is still OK.
|
||||
version |= JSVERSION_HAS_XML;
|
||||
version |= js::VersionFlags::HAS_XML;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1058,7 +1058,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
// our implementation knowledge to reuse JSVERSION_HAS_XML as a
|
||||
// safe version flag. This is still OK if version is
|
||||
// JSVERSION_UNKNOWN (-1),
|
||||
version |= JSVERSION_HAS_XML;
|
||||
version |= js::VersionFlags::HAS_XML;
|
||||
|
||||
nsAutoString value;
|
||||
rv = parser.GetParameter("e4x", value);
|
||||
|
@ -1067,7 +1067,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
return rv;
|
||||
} else {
|
||||
if (value.Length() == 1 && value[0] == '0')
|
||||
version &= ~JSVERSION_HAS_XML;
|
||||
version &= ~js::VersionFlags::HAS_XML;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1081,7 +1081,7 @@ XULContentSinkImpl::OpenScript(const PRUnichar** aAttributes,
|
|||
|
||||
// Even when JS version < 1.6 is specified, E4X is
|
||||
// turned on in XUL.
|
||||
version |= JSVERSION_HAS_XML;
|
||||
version |= js::VersionFlags::HAS_XML;
|
||||
}
|
||||
}
|
||||
aAttributes += 2;
|
||||
|
|
|
@ -311,51 +311,6 @@ nsCCMemoryPressureObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
class nsJSVersionSetter {
|
||||
public:
|
||||
nsJSVersionSetter(JSContext *aContext, PRUint32 aVersion);
|
||||
~nsJSVersionSetter();
|
||||
|
||||
private:
|
||||
JSContext* mContext;
|
||||
uint32 mOldOptions;
|
||||
JSVersion mOldVersion;
|
||||
JSBool mOptionsChanged;
|
||||
};
|
||||
|
||||
nsJSVersionSetter::nsJSVersionSetter(JSContext *aContext, PRUint32 aVersion)
|
||||
: mContext(aContext)
|
||||
{
|
||||
// JSVERSION_HAS_XML may be set in our version mask - however, we can't
|
||||
// simply pass this directly to JS_SetOptions as it masks out that bit -
|
||||
// the only way to make this happen is via JS_SetOptions.
|
||||
JSBool hasxml = (aVersion & JSVERSION_HAS_XML) != 0;
|
||||
mOldOptions = ::JS_GetOptions(mContext);
|
||||
mOptionsChanged = ((hasxml) ^ !!(mOldOptions & JSOPTION_XML));
|
||||
|
||||
if (mOptionsChanged) {
|
||||
::JS_SetOptions(mContext,
|
||||
hasxml
|
||||
? mOldOptions | JSOPTION_XML
|
||||
: mOldOptions & ~JSOPTION_XML);
|
||||
}
|
||||
|
||||
// Change the version - this is cheap when the versions match, so no need
|
||||
// to optimize here...
|
||||
JSVersion newVer = (JSVersion)(aVersion & JSVERSION_MASK);
|
||||
mOldVersion = ::JS_SetVersion(mContext, newVer);
|
||||
}
|
||||
|
||||
nsJSVersionSetter::~nsJSVersionSetter()
|
||||
{
|
||||
::JS_SetVersion(mContext, mOldVersion);
|
||||
|
||||
if (mOptionsChanged) {
|
||||
::JS_SetOptions(mContext, mOldOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************
|
||||
************************** AutoFree ****************************
|
||||
****************************************************************/
|
||||
|
@ -1529,7 +1484,6 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
|||
if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) {
|
||||
|
||||
JSAutoRequest ar(mContext);
|
||||
nsJSVersionSetter setVersion(mContext, aVersion);
|
||||
|
||||
JSAutoCrossCompartmentCall accc;
|
||||
if (!accc.enter(mContext, (JSObject *)aScopeObject)) {
|
||||
|
@ -1540,14 +1494,15 @@ nsJSContext::EvaluateStringWithValue(const nsAString& aScript,
|
|||
|
||||
++mExecuteDepth;
|
||||
|
||||
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
|
||||
(JSObject *)aScopeObject,
|
||||
jsprin,
|
||||
(jschar*)PromiseFlatString(aScript).get(),
|
||||
aScript.Length(),
|
||||
aURL,
|
||||
aLineNo,
|
||||
&val);
|
||||
ok = ::JS_EvaluateUCScriptForPrincipalsVersion(mContext,
|
||||
(JSObject *)aScopeObject,
|
||||
jsprin,
|
||||
(jschar*)PromiseFlatString(aScript).get(),
|
||||
aScript.Length(),
|
||||
aURL,
|
||||
aLineNo,
|
||||
&val,
|
||||
JSVersion(aVersion));
|
||||
|
||||
--mExecuteDepth;
|
||||
|
||||
|
@ -1737,16 +1692,15 @@ nsJSContext::EvaluateString(const nsAString& aScript,
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsJSVersionSetter setVersion(mContext, aVersion);
|
||||
|
||||
ok = ::JS_EvaluateUCScriptForPrincipals(mContext,
|
||||
(JSObject *)aScopeObject,
|
||||
jsprin,
|
||||
(jschar*)PromiseFlatString(aScript).get(),
|
||||
aScript.Length(),
|
||||
aURL,
|
||||
aLineNo,
|
||||
vp);
|
||||
ok = ::JS_EvaluateUCScriptForPrincipalsVersion(mContext,
|
||||
(JSObject *)aScopeObject,
|
||||
jsprin,
|
||||
(jschar*)PromiseFlatString(aScript).get(),
|
||||
aScript.Length(),
|
||||
aURL,
|
||||
aLineNo,
|
||||
vp,
|
||||
JSVersion(aVersion));
|
||||
|
||||
if (!ok) {
|
||||
// Tell XPConnect about any pending exceptions. This is needed
|
||||
|
@ -1826,16 +1780,16 @@ nsJSContext::CompileScript(const PRUnichar* aText,
|
|||
// check it isn't JSVERSION_UNKNOWN.
|
||||
if (ok && ((JSVersion)aVersion) != JSVERSION_UNKNOWN) {
|
||||
JSAutoRequest ar(mContext);
|
||||
nsJSVersionSetter setVersion(mContext, aVersion);
|
||||
|
||||
JSScript* script =
|
||||
::JS_CompileUCScriptForPrincipals(mContext,
|
||||
(JSObject *)aScopeObject,
|
||||
jsprin,
|
||||
(jschar*) aText,
|
||||
aTextLength,
|
||||
aURL,
|
||||
aLineNo);
|
||||
::JS_CompileUCScriptForPrincipalsVersion(mContext,
|
||||
(JSObject *)aScopeObject,
|
||||
jsprin,
|
||||
(jschar*) aText,
|
||||
aTextLength,
|
||||
aURL,
|
||||
aLineNo,
|
||||
JSVersion(aVersion));
|
||||
if (script) {
|
||||
JSObject *scriptObject = ::JS_NewScriptObject(mContext, script);
|
||||
if (scriptObject) {
|
||||
|
@ -2032,15 +1986,14 @@ nsJSContext::CompileEventHandler(nsIAtom *aName,
|
|||
// Therefore we never bother compiling with principals.
|
||||
// (that probably means we should avoid JS_CompileUCFunctionForPrincipals!)
|
||||
JSAutoRequest ar(mContext);
|
||||
nsJSVersionSetter setVersion(mContext, aVersion);
|
||||
|
||||
JSFunction* fun =
|
||||
::JS_CompileUCFunctionForPrincipals(mContext,
|
||||
nsnull, nsnull,
|
||||
nsAtomCString(aName).get(), aArgCount, aArgNames,
|
||||
(jschar*)PromiseFlatString(aBody).get(),
|
||||
aBody.Length(),
|
||||
aURL, aLineNo);
|
||||
::JS_CompileUCFunctionForPrincipalsVersion(mContext,
|
||||
nsnull, nsnull,
|
||||
nsAtomCString(aName).get(), aArgCount, aArgNames,
|
||||
(jschar*)PromiseFlatString(aBody).get(),
|
||||
aBody.Length(),
|
||||
aURL, aLineNo, JSVersion(aVersion));
|
||||
|
||||
if (!fun) {
|
||||
ReportPendingException();
|
||||
|
@ -2095,16 +2048,16 @@ nsJSContext::CompileFunction(void* aTarget,
|
|||
JSObject *target = (JSObject*)aTarget;
|
||||
|
||||
JSAutoRequest ar(mContext);
|
||||
nsJSVersionSetter setVersion(mContext, aVersion);
|
||||
|
||||
JSFunction* fun =
|
||||
::JS_CompileUCFunctionForPrincipals(mContext,
|
||||
aShared ? nsnull : target, jsprin,
|
||||
PromiseFlatCString(aName).get(),
|
||||
aArgCount, aArgArray,
|
||||
(jschar*)PromiseFlatString(aBody).get(),
|
||||
aBody.Length(),
|
||||
aURL, aLineNo);
|
||||
::JS_CompileUCFunctionForPrincipalsVersion(mContext,
|
||||
aShared ? nsnull : target, jsprin,
|
||||
PromiseFlatCString(aName).get(),
|
||||
aArgCount, aArgArray,
|
||||
(jschar*)PromiseFlatString(aBody).get(),
|
||||
aBody.Length(),
|
||||
aURL, aLineNo,
|
||||
JSVersion(aVersion));
|
||||
|
||||
if (jsprin)
|
||||
JSPRINCIPALS_DROP(mContext, jsprin);
|
||||
|
|
125
js/src/jsapi.cpp
125
js/src/jsapi.cpp
|
@ -108,6 +108,38 @@
|
|||
|
||||
using namespace js;
|
||||
|
||||
class AutoVersionAPI
|
||||
{
|
||||
JSContext * const cx;
|
||||
JSVersion oldVersion;
|
||||
bool oldVersionWasOverride;
|
||||
uint32 oldOptions;
|
||||
|
||||
public:
|
||||
explicit AutoVersionAPI(JSContext *cx, JSVersion newVersion)
|
||||
: cx(cx), oldVersion(cx->findVersion()), oldVersionWasOverride(cx->isVersionOverridden()),
|
||||
oldOptions(cx->options) {
|
||||
JS_ASSERT(!VersionExtractFlags(newVersion) ||
|
||||
VersionExtractFlags(newVersion) == VersionFlags::HAS_XML);
|
||||
cx->options = VersionHasXML(newVersion)
|
||||
? (cx->options | JSOPTION_XML)
|
||||
: (cx->options & ~JSOPTION_XML);
|
||||
cx->maybeOverrideVersion(newVersion);
|
||||
SyncOptionsToVersion(cx);
|
||||
}
|
||||
|
||||
~AutoVersionAPI() {
|
||||
cx->options = oldOptions;
|
||||
if (oldVersionWasOverride) {
|
||||
JS_ALWAYS_TRUE(cx->maybeOverrideVersion(oldVersion));
|
||||
} else {
|
||||
cx->clearVersionOverride();
|
||||
cx->setDefaultVersion(oldVersion);
|
||||
}
|
||||
JS_ASSERT(cx->findVersion() == oldVersion);
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef HAVE_VA_LIST_AS_ARRAY
|
||||
#define JS_ADDRESSOF_VA_LIST(ap) ((va_list *)(ap))
|
||||
#else
|
||||
|
@ -983,28 +1015,40 @@ JS_ContextIterator(JSRuntime *rt, JSContext **iterp)
|
|||
JS_PUBLIC_API(JSVersion)
|
||||
JS_GetVersion(JSContext *cx)
|
||||
{
|
||||
return JSVERSION_NUMBER(cx);
|
||||
return VersionNumber(cx->findVersion());
|
||||
}
|
||||
|
||||
static void
|
||||
CheckOptionVersionSync(JSContext *cx)
|
||||
{
|
||||
#if DEBUG
|
||||
uint32 options = cx->options;
|
||||
JSVersion version = cx->findVersion();
|
||||
JS_ASSERT(OptionsHasXML(options) == VersionHasXML(version));
|
||||
JS_ASSERT(OptionsHasAnonFunFix(options) == VersionHasAnonFunFix(version));
|
||||
#endif
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSVersion)
|
||||
JS_SetVersion(JSContext *cx, JSVersion version)
|
||||
JS_SetVersion(JSContext *cx, JSVersion newVersion)
|
||||
{
|
||||
JSVersion oldVersion;
|
||||
JS_ASSERT(VersionIsKnown(newVersion));
|
||||
JS_ASSERT(!VersionHasFlags(newVersion));
|
||||
JSVersion newVersionNumber = newVersion;
|
||||
|
||||
JS_ASSERT(version != JSVERSION_UNKNOWN);
|
||||
JS_ASSERT((version & ~JSVERSION_MASK) == 0);
|
||||
|
||||
oldVersion = JSVERSION_NUMBER(cx);
|
||||
if (version == oldVersion)
|
||||
return oldVersion;
|
||||
JSVersion oldVersion = cx->findVersion();
|
||||
JSVersion oldVersionNumber = VersionNumber(oldVersion);
|
||||
if (oldVersionNumber == newVersionNumber)
|
||||
return oldVersionNumber; /* No override actually occurs! */
|
||||
|
||||
/* We no longer support 1.4 or below. */
|
||||
if (version != JSVERSION_DEFAULT && version <= JSVERSION_1_4)
|
||||
return oldVersion;
|
||||
if (newVersionNumber != JSVERSION_DEFAULT && newVersionNumber <= JSVERSION_1_4)
|
||||
return oldVersionNumber;
|
||||
|
||||
cx->version = (cx->version & ~JSVERSION_MASK) | version;
|
||||
js_OnVersionChange(cx);
|
||||
return oldVersion;
|
||||
VersionCloneFlags(oldVersion, &newVersion);
|
||||
cx->maybeOverrideVersion(newVersion);
|
||||
CheckOptionVersionSync(cx);
|
||||
return oldVersionNumber;
|
||||
}
|
||||
|
||||
static struct v2smap {
|
||||
|
@ -1051,6 +1095,11 @@ JS_StringToVersion(const char *string)
|
|||
JS_PUBLIC_API(uint32)
|
||||
JS_GetOptions(JSContext *cx)
|
||||
{
|
||||
/*
|
||||
* Can't check option/version synchronization here.
|
||||
* We may have been synchronized with a script version that was formerly on
|
||||
* the stack, but has now been popped.
|
||||
*/
|
||||
return cx->options;
|
||||
}
|
||||
|
||||
|
@ -1060,8 +1109,14 @@ JS_SetOptions(JSContext *cx, uint32 options)
|
|||
AutoLockGC lock(cx->runtime);
|
||||
uint32 oldopts = cx->options;
|
||||
cx->options = options;
|
||||
js_SyncOptionsToVersion(cx);
|
||||
#if DEBUG
|
||||
bool changedVersion =
|
||||
#else
|
||||
(void)
|
||||
#endif
|
||||
SyncOptionsToVersion(cx);
|
||||
cx->updateJITEnabled();
|
||||
CheckOptionVersionSync(cx);
|
||||
return oldopts;
|
||||
}
|
||||
|
||||
|
@ -1069,10 +1124,12 @@ JS_PUBLIC_API(uint32)
|
|||
JS_ToggleOptions(JSContext *cx, uint32 options)
|
||||
{
|
||||
AutoLockGC lock(cx->runtime);
|
||||
CheckOptionVersionSync(cx);
|
||||
uint32 oldopts = cx->options;
|
||||
cx->options ^= options;
|
||||
js_SyncOptionsToVersion(cx);
|
||||
(void) SyncOptionsToVersion(cx);
|
||||
cx->updateJITEnabled();
|
||||
CheckOptionVersionSync(cx);
|
||||
return oldopts;
|
||||
}
|
||||
|
||||
|
@ -4291,6 +4348,17 @@ JS_OPTIONS_TO_TCFLAGS(JSContext *cx)
|
|||
((cx->options & JSOPTION_NO_SCRIPT_RVAL) ? TCF_NO_SCRIPT_RVAL : 0);
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals,
|
||||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno,
|
||||
JSVersion version)
|
||||
{
|
||||
AutoVersionAPI avi(cx, version);
|
||||
return JS_CompileUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSScript *)
|
||||
JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj, JSPrincipals *principals,
|
||||
const jschar *chars, size_t length,
|
||||
|
@ -4486,6 +4554,19 @@ JS_DestroyScript(JSContext *cx, JSScript *script)
|
|||
JS_ASSERT(script->u.object);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals, const char *name,
|
||||
uintN nargs, const char **argnames,
|
||||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno,
|
||||
JSVersion version)
|
||||
{
|
||||
AutoVersionAPI avi(cx, version);
|
||||
return JS_CompileUCFunctionForPrincipals(cx, obj, principals, name, nargs, argnames, chars,
|
||||
length, filename, lineno);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSFunction *)
|
||||
JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals, const char *name,
|
||||
|
@ -4652,6 +4733,18 @@ JS_ExecuteScript(JSContext *cx, JSObject *obj, JSScript *script, jsval *rval)
|
|||
return ok;
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals,
|
||||
const jschar *chars, uintN length,
|
||||
const char *filename, uintN lineno,
|
||||
jsval *rval, JSVersion version)
|
||||
{
|
||||
AutoVersionAPI avi(cx, version);
|
||||
return JS_EvaluateUCScriptForPrincipals(cx, obj, principals, chars, length, filename, lineno,
|
||||
rval);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals,
|
||||
|
|
|
@ -2371,6 +2371,13 @@ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
|
|||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals,
|
||||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno,
|
||||
JSVersion version);
|
||||
|
||||
extern JS_PUBLIC_API(JSScript *)
|
||||
JS_CompileFile(JSContext *cx, JSObject *obj, const char *filename);
|
||||
|
||||
|
@ -2438,6 +2445,14 @@ JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
|
|||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno);
|
||||
|
||||
extern JS_PUBLIC_API(JSFunction *)
|
||||
JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals, const char *name,
|
||||
uintN nargs, const char **argnames,
|
||||
const jschar *chars, size_t length,
|
||||
const char *filename, uintN lineno,
|
||||
JSVersion version);
|
||||
|
||||
extern JS_PUBLIC_API(JSString *)
|
||||
JS_DecompileScript(JSContext *cx, JSScript *script, const char *name,
|
||||
uintN indent);
|
||||
|
@ -2517,6 +2532,13 @@ JS_EvaluateUCScript(JSContext *cx, JSObject *obj,
|
|||
const char *filename, uintN lineno,
|
||||
jsval *rval);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals,
|
||||
const jschar *chars, uintN length,
|
||||
const char *filename, uintN lineno,
|
||||
jsval *rval, JSVersion version);
|
||||
|
||||
extern JS_PUBLIC_API(JSBool)
|
||||
JS_EvaluateUCScriptForPrincipals(JSContext *cx, JSObject *obj,
|
||||
JSPrincipals *principals,
|
||||
|
|
|
@ -726,54 +726,20 @@ js_PurgeThreads(JSContext *cx)
|
|||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* JSOPTION_XML and JSOPTION_ANONFUNFIX must be part of the JS version
|
||||
* associated with scripts, so in addition to storing them in cx->options we
|
||||
* duplicate them in cx->version (script->version, etc.) and ensure each bit
|
||||
* remains synchronized between the two through these two functions.
|
||||
*/
|
||||
void
|
||||
js_SyncOptionsToVersion(JSContext* cx)
|
||||
bool
|
||||
js::SyncOptionsToVersion(JSContext* cx)
|
||||
{
|
||||
if (cx->options & JSOPTION_XML)
|
||||
cx->version |= JSVERSION_HAS_XML;
|
||||
else
|
||||
cx->version &= ~JSVERSION_HAS_XML;
|
||||
if (cx->options & JSOPTION_ANONFUNFIX)
|
||||
cx->version |= JSVERSION_ANONFUNFIX;
|
||||
else
|
||||
cx->version &= ~JSVERSION_ANONFUNFIX;
|
||||
}
|
||||
|
||||
inline void
|
||||
js_SyncVersionToOptions(JSContext* cx)
|
||||
{
|
||||
if (cx->version & JSVERSION_HAS_XML)
|
||||
cx->options |= JSOPTION_XML;
|
||||
else
|
||||
cx->options &= ~JSOPTION_XML;
|
||||
if (cx->version & JSVERSION_ANONFUNFIX)
|
||||
cx->options |= JSOPTION_ANONFUNFIX;
|
||||
else
|
||||
cx->options &= ~JSOPTION_ANONFUNFIX;
|
||||
}
|
||||
|
||||
void
|
||||
js_OnVersionChange(JSContext *cx)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JSVersion version = JSVERSION_NUMBER(cx);
|
||||
|
||||
JS_ASSERT(version == JSVERSION_DEFAULT || version >= JSVERSION_ECMA_3);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
js_SetVersion(JSContext *cx, JSVersion version)
|
||||
{
|
||||
cx->version = version;
|
||||
js_SyncVersionToOptions(cx);
|
||||
js_OnVersionChange(cx);
|
||||
JSVersion version = cx->findVersion();
|
||||
uint32 options = cx->options;
|
||||
if (OptionsHasXML(options) == VersionHasXML(version) &&
|
||||
OptionsHasAnonFunFix(options) == VersionHasAnonFunFix(version)) {
|
||||
/* No need to override. */
|
||||
return false;
|
||||
}
|
||||
VersionSetXML(&version, OptionsHasXML(options));
|
||||
VersionSetAnonFunFix(&version, OptionsHasAnonFunFix(options));
|
||||
cx->maybeOverrideVersion(version);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSContext *
|
||||
|
@ -799,7 +765,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize)
|
|||
#endif
|
||||
cx->scriptStackQuota = JS_DEFAULT_SCRIPT_STACK_QUOTA;
|
||||
JS_STATIC_ASSERT(JSVERSION_DEFAULT == 0);
|
||||
JS_ASSERT(cx->version == JSVERSION_DEFAULT);
|
||||
JS_ASSERT(cx->findVersion() == JSVERSION_DEFAULT);
|
||||
VOUCH_DOES_NOT_REQUIRE_STACK();
|
||||
|
||||
JS_InitArenaPool(&cx->tempPool, "temp", TEMP_POOL_CHUNK_SIZE, sizeof(jsdouble),
|
||||
|
|
238
js/src/jscntxt.h
238
js/src/jscntxt.h
|
@ -2019,6 +2019,97 @@ class RegExpStatics
|
|||
void getRightContext(JSSubString *out) const;
|
||||
};
|
||||
|
||||
#define JS_HAS_OPTION(cx,option) (((cx)->options & (option)) != 0)
|
||||
#define JS_HAS_STRICT_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_STRICT)
|
||||
#define JS_HAS_WERROR_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_WERROR)
|
||||
#define JS_HAS_COMPILE_N_GO_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_COMPILE_N_GO)
|
||||
#define JS_HAS_ATLINE_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_ATLINE)
|
||||
|
||||
static inline bool
|
||||
OptionsHasXML(uint32 options)
|
||||
{
|
||||
return !!(options & JSOPTION_XML);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
OptionsHasAnonFunFix(uint32 options)
|
||||
{
|
||||
return !!(options & JSOPTION_ANONFUNFIX);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
OptionsSameVersionFlags(uint32 self, uint32 other)
|
||||
{
|
||||
static const uint32 mask = JSOPTION_XML | JSOPTION_ANONFUNFIX;
|
||||
return !((self & mask) ^ (other & mask));
|
||||
}
|
||||
|
||||
namespace VersionFlags {
|
||||
static const uint32 MASK = 0x0FFF; /* see JSVersion in jspubtd.h */
|
||||
static const uint32 HAS_XML = 0x1000; /* flag induced by XML option */
|
||||
static const uint32 ANONFUNFIX = 0x2000; /* see jsapi.h comment on JSOPTION_ANONFUNFIX */
|
||||
}
|
||||
|
||||
static inline bool
|
||||
VersionHasXML(JSVersion version)
|
||||
{
|
||||
return !!(version & VersionFlags::HAS_XML);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
VersionHasAnonFunFix(JSVersion version)
|
||||
{
|
||||
return !!(version & VersionFlags::ANONFUNFIX);
|
||||
}
|
||||
|
||||
static inline void
|
||||
VersionSetXML(JSVersion *version, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
*version = JSVersion(uint32(*version) | VersionFlags::HAS_XML);
|
||||
else
|
||||
*version = JSVersion(uint32(*version) & ~VersionFlags::HAS_XML);
|
||||
}
|
||||
|
||||
static inline void
|
||||
VersionSetAnonFunFix(JSVersion *version, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
*version = JSVersion(uint32(*version) | VersionFlags::ANONFUNFIX);
|
||||
else
|
||||
*version = JSVersion(uint32(*version) & ~VersionFlags::ANONFUNFIX);
|
||||
}
|
||||
|
||||
static inline JSVersion
|
||||
VersionExtractFlags(JSVersion version)
|
||||
{
|
||||
return JSVersion(uint32(version) & ~VersionFlags::MASK);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
VersionHasFlags(JSVersion version)
|
||||
{
|
||||
return !!VersionExtractFlags(version);
|
||||
}
|
||||
|
||||
static inline JSVersion
|
||||
VersionNumber(JSVersion version)
|
||||
{
|
||||
return JSVersion(uint32(version) & VersionFlags::MASK);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
VersionIsKnown(JSVersion version)
|
||||
{
|
||||
return VersionNumber(version) != JSVERSION_UNKNOWN;
|
||||
}
|
||||
|
||||
static inline void
|
||||
VersionCloneFlags(JSVersion src, JSVersion *dst)
|
||||
{
|
||||
*dst = JSVersion(uint32(VersionNumber(*dst)) | uint32(VersionExtractFlags(src)));
|
||||
}
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
struct JSContext
|
||||
|
@ -2028,9 +2119,13 @@ struct JSContext
|
|||
/* JSRuntime contextList linkage. */
|
||||
JSCList link;
|
||||
|
||||
/* Runtime version control identifier. */
|
||||
uint16 version;
|
||||
private:
|
||||
/* See JSContext::findVersion. */
|
||||
JSVersion defaultVersion; /* script compilation version */
|
||||
JSVersion versionOverride; /* supercedes defaultVersion when valid */
|
||||
bool hasVersionOverride;
|
||||
|
||||
public:
|
||||
/* Per-context options. */
|
||||
uint32 options; /* see jsapi.h for JSOPTION_* */
|
||||
|
||||
|
@ -2189,11 +2284,9 @@ struct JSContext
|
|||
*/
|
||||
js::StackSegment *containingSegment(const JSStackFrame *target);
|
||||
|
||||
/*
|
||||
* Search the call stack for the nearest frame with static level targetLevel.
|
||||
*/
|
||||
JSStackFrame *findFrameAtLevel(uintN targetLevel) {
|
||||
JSStackFrame *fp = this->regs->fp;
|
||||
/* Search the call stack for the nearest frame with static level targetLevel. */
|
||||
JSStackFrame *findFrameAtLevel(uintN targetLevel) const {
|
||||
JSStackFrame *fp = regs->fp;
|
||||
while (true) {
|
||||
JS_ASSERT(fp && fp->isScriptFrame());
|
||||
if (fp->script()->staticLevel == targetLevel)
|
||||
|
@ -2203,6 +2296,64 @@ struct JSContext
|
|||
return fp;
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* The default script compilation version can be set iff there is no code running.
|
||||
* This typically occurs via the JSAPI right after a context is constructed.
|
||||
*/
|
||||
bool canSetDefaultVersion() const { return !regs && !hasVersionOverride; }
|
||||
|
||||
/* Force a version for future script compilation. */
|
||||
void overrideVersion(JSVersion newVersion) {
|
||||
JS_ASSERT(!canSetDefaultVersion());
|
||||
versionOverride = newVersion;
|
||||
hasVersionOverride = true;
|
||||
}
|
||||
|
||||
public:
|
||||
void clearVersionOverride() { hasVersionOverride = false; }
|
||||
bool isVersionOverridden() const { return hasVersionOverride; }
|
||||
|
||||
/* Set the default script compilation version. */
|
||||
void setDefaultVersion(JSVersion version) { defaultVersion = version; }
|
||||
|
||||
/*
|
||||
* Set the default version if possible; otherwise, force the version.
|
||||
* Return whether an override occurred.
|
||||
*/
|
||||
bool maybeOverrideVersion(JSVersion newVersion) {
|
||||
if (canSetDefaultVersion()) {
|
||||
setDefaultVersion(newVersion);
|
||||
return false;
|
||||
}
|
||||
overrideVersion(newVersion);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return:
|
||||
* - The override version, if there is an override version.
|
||||
* - The newest scripted frame's version, if there is such a frame.
|
||||
* - The default verion.
|
||||
*
|
||||
* @note If this ever shows up in a profile, just add caching!
|
||||
*/
|
||||
JSVersion findVersion() const {
|
||||
if (hasVersionOverride)
|
||||
return versionOverride;
|
||||
|
||||
if (regs) {
|
||||
/* There may be a scripted function somewhere on the stack! */
|
||||
JSStackFrame *fp = regs->fp;
|
||||
while (fp && !fp->isScriptFrame())
|
||||
fp = fp->prev();
|
||||
if (fp)
|
||||
return fp->script()->getVersion();
|
||||
}
|
||||
|
||||
return defaultVersion;
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
JSThread *thread;
|
||||
unsigned outstandingRequests;/* number of JS_BeginRequest calls
|
||||
|
@ -2950,49 +3101,6 @@ class JSAutoResolveFlags
|
|||
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
/*
|
||||
* Slightly more readable macros for testing per-context option settings (also
|
||||
* to hide bitset implementation detail).
|
||||
*
|
||||
* JSOPTION_XML must be handled specially in order to propagate from compile-
|
||||
* to run-time (from cx->options to script->version/cx->version). To do that,
|
||||
* we copy JSOPTION_XML from cx->options into cx->version as JSVERSION_HAS_XML
|
||||
* whenever options are set, and preserve this XML flag across version number
|
||||
* changes done via the JS_SetVersion API.
|
||||
*
|
||||
* But when executing a script or scripted function, the interpreter changes
|
||||
* cx->version, including the XML flag, to script->version. Thus JSOPTION_XML
|
||||
* is a compile-time option that causes a run-time version change during each
|
||||
* activation of the compiled script. That version change has the effect of
|
||||
* changing JS_HAS_XML_OPTION, so that any compiling done via eval enables XML
|
||||
* support. If an XML-enabled script or function calls a non-XML function,
|
||||
* the flag bit will be cleared during the callee's activation.
|
||||
*
|
||||
* Note that JS_SetVersion API calls never pass JSVERSION_HAS_XML or'd into
|
||||
* that API's version parameter.
|
||||
*
|
||||
* Note also that script->version must contain this XML option flag in order
|
||||
* for XDR'ed scripts to serialize and deserialize with that option preserved
|
||||
* for detection at run-time. We can't copy other compile-time options into
|
||||
* script->version because that would break backward compatibility (certain
|
||||
* other options, e.g. JSOPTION_VAROBJFIX, are analogous to JSOPTION_XML).
|
||||
*/
|
||||
#define JS_HAS_OPTION(cx,option) (((cx)->options & (option)) != 0)
|
||||
#define JS_HAS_STRICT_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_STRICT)
|
||||
#define JS_HAS_WERROR_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_WERROR)
|
||||
#define JS_HAS_COMPILE_N_GO_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_COMPILE_N_GO)
|
||||
#define JS_HAS_ATLINE_OPTION(cx) JS_HAS_OPTION(cx, JSOPTION_ATLINE)
|
||||
|
||||
#define JSVERSION_MASK 0x0FFF /* see JSVersion in jspubtd.h */
|
||||
#define JSVERSION_HAS_XML 0x1000 /* flag induced by XML option */
|
||||
#define JSVERSION_ANONFUNFIX 0x2000 /* see jsapi.h, the comments
|
||||
for JSOPTION_ANONFUNFIX */
|
||||
|
||||
#define JSVERSION_NUMBER(cx) ((JSVersion)((cx)->version & \
|
||||
JSVERSION_MASK))
|
||||
#define JS_HAS_XML_OPTION(cx) ((cx)->version & JSVERSION_HAS_XML || \
|
||||
JSVERSION_NUMBER(cx) >= JSVERSION_1_6)
|
||||
|
||||
extern JSThreadData *
|
||||
js_CurrentThreadData(JSRuntime *rt);
|
||||
|
||||
|
@ -3046,30 +3154,16 @@ class ThreadDataIter
|
|||
|
||||
#endif /* !JS_THREADSAFE */
|
||||
|
||||
/*
|
||||
* If necessary, push the option flags that affect script compilation to the current version.
|
||||
* Note this may cause a version override -- see JSContext::overrideVersion.
|
||||
* Return whether a version change occurred.
|
||||
*/
|
||||
extern bool
|
||||
SyncOptionsToVersion(JSContext *cx);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
/*
|
||||
* Ensures the JSOPTION_XML and JSOPTION_ANONFUNFIX bits of cx->options are
|
||||
* reflected in cx->version, since each bit must travel with a script that has
|
||||
* it set.
|
||||
*/
|
||||
extern void
|
||||
js_SyncOptionsToVersion(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Common subroutine of JS_SetVersion and js_SetVersion, to update per-context
|
||||
* data that depends on version.
|
||||
*/
|
||||
extern void
|
||||
js_OnVersionChange(JSContext *cx);
|
||||
|
||||
/*
|
||||
* Unlike the JS_SetVersion API, this function stores JSVERSION_HAS_XML and
|
||||
* any future non-version-number flags induced by compiler options.
|
||||
*/
|
||||
extern void
|
||||
js_SetVersion(JSContext *cx, JSVersion version);
|
||||
|
||||
/*
|
||||
* Create and destroy functions for JSContext, which is manually allocated
|
||||
* and exclusively owned.
|
||||
|
|
|
@ -1303,7 +1303,7 @@ JS_GetScriptLineExtent(JSContext *cx, JSScript *script)
|
|||
JS_PUBLIC_API(JSVersion)
|
||||
JS_GetScriptVersion(JSContext *cx, JSScript *script)
|
||||
{
|
||||
return (JSVersion) (script->version & JSVERSION_MASK);
|
||||
return VersionNumber(script->getVersion());
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -1789,6 +1789,12 @@ JS_MakeSystemObject(JSContext *cx, JSObject *obj)
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
js_RevertVersion(JSContext *cx)
|
||||
{
|
||||
cx->clearVersionOverride();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(const JSDebugHooks *)
|
||||
JS_GetGlobalDebugHooks(JSRuntime *rt)
|
||||
{
|
||||
|
|
|
@ -492,6 +492,9 @@ JS_MakeSystemObject(JSContext *cx, JSObject *obj);
|
|||
|
||||
/************************************************************************/
|
||||
|
||||
extern JS_FRIEND_API(void)
|
||||
js_RevertVersion(JSContext *cx);
|
||||
|
||||
extern JS_PUBLIC_API(const JSDebugHooks *)
|
||||
JS_GetGlobalDebugHooks(JSRuntime *rt);
|
||||
|
||||
|
|
|
@ -474,7 +474,7 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSFunction *fun)
|
|||
wscript->savedCallerFun = script->savedCallerFun;
|
||||
wscript->hasSharps = script->hasSharps;
|
||||
wscript->strictModeCode = script->strictModeCode;
|
||||
wscript->version = script->version;
|
||||
wscript->setVersion(script->getVersion());
|
||||
wscript->nfixed = script->nfixed;
|
||||
wscript->filename = script->filename;
|
||||
wscript->lineno = script->lineno;
|
||||
|
@ -2738,7 +2738,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
|||
|
||||
/* Initialize a tokenstream that reads from the given string. */
|
||||
TokenStream ts(cx);
|
||||
if (!ts.init(collected_args, args_length, NULL, filename, lineno)) {
|
||||
if (!ts.init(cx->findVersion(), collected_args, args_length, NULL, filename, lineno)) {
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
|
|
@ -2097,7 +2097,6 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, uintN
|
|||
script = regs.fp->script(); \
|
||||
argv = regs.fp->maybeFormalArgs(); \
|
||||
atoms = FrameAtomBase(cx, regs.fp); \
|
||||
currentVersion = (JSVersion) script->version; \
|
||||
JS_ASSERT(cx->regs == ®s); \
|
||||
if (cx->throwing) \
|
||||
goto error; \
|
||||
|
@ -2213,20 +2212,6 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, uintN
|
|||
if (!entryFrame)
|
||||
entryFrame = regs.fp;
|
||||
|
||||
/*
|
||||
* Optimized Get and SetVersion for proper script language versioning.
|
||||
*
|
||||
* If any native method or a Class ObjectOps hook calls js_SetVersion
|
||||
* and changes cx->version, the effect will "stick" and we will stop
|
||||
* maintaining currentVersion. This is relied upon by testsuites, for
|
||||
* the most part -- web browsers select version before compiling and not
|
||||
* at run-time.
|
||||
*/
|
||||
JSVersion currentVersion = (JSVersion) script->version;
|
||||
JSVersion originalVersion = (JSVersion) cx->version;
|
||||
if (currentVersion != originalVersion)
|
||||
js_SetVersion(cx, currentVersion);
|
||||
|
||||
/*
|
||||
* Initialize the index segment register used by LOAD_ATOM and
|
||||
* GET_FULL_INDEX macros below. As a register we use a pointer based on
|
||||
|
@ -2537,13 +2522,6 @@ BEGIN_CASE(JSOP_STOP)
|
|||
|
||||
Probes::exitJSFun(cx, regs.fp->maybeFun());
|
||||
|
||||
/* Restore context version only if callee hasn't set version. */
|
||||
if (JS_LIKELY(cx->version == currentVersion)) {
|
||||
currentVersion = regs.fp->callerVersion();
|
||||
if (currentVersion != cx->version)
|
||||
js_SetVersion(cx, currentVersion);
|
||||
}
|
||||
|
||||
/*
|
||||
* If inline-constructing, replace primitive rval with the new object
|
||||
* passed in via |this|, and instrument this constructor invocation.
|
||||
|
@ -4445,14 +4423,6 @@ BEGIN_CASE(JSOP_APPLY)
|
|||
newfp->initCallFrame(cx, *callee, newfun, argc, flags);
|
||||
SetValueRangeToUndefined(newfp->slots(), newscript->nfixed);
|
||||
|
||||
/* Switch version if currentVersion wasn't overridden. */
|
||||
newfp->setCallerVersion((JSVersion) cx->version);
|
||||
if (JS_LIKELY(cx->version == currentVersion)) {
|
||||
currentVersion = (JSVersion) newscript->version;
|
||||
if (JS_UNLIKELY(currentVersion != cx->version))
|
||||
js_SetVersion(cx, currentVersion);
|
||||
}
|
||||
|
||||
/* Officially push the frame. */
|
||||
stack.pushInlineFrame(cx, newscript, newfp, ®s);
|
||||
|
||||
|
@ -6753,9 +6723,6 @@ END_CASE(JSOP_ARRAYPUSH)
|
|||
JS_ASSERT_IF(!regs.fp->isGeneratorFrame(), !regs.fp->hasBlockChain());
|
||||
JS_ASSERT_IF(!regs.fp->isGeneratorFrame(), !js_IsActiveWithOrBlock(cx, ®s.fp->scopeChain(), 0));
|
||||
|
||||
/* Undo the remaining effects committed on entry to Interpret. */
|
||||
if (cx->version == currentVersion && currentVersion != originalVersion)
|
||||
js_SetVersion(cx, originalVersion);
|
||||
--cx->interpLevel;
|
||||
|
||||
return interpReturnOK;
|
||||
|
|
|
@ -126,7 +126,6 @@ struct JSStackFrame
|
|||
|
||||
/* TODO: remove */
|
||||
void *ncode_; /* bug 535912 */
|
||||
JSVersion callerVersion_; /* bug 535912 */
|
||||
JSObject *blockChain_; /* bug 540675 */
|
||||
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
|
@ -553,16 +552,6 @@ struct JSStackFrame
|
|||
flags_ |= JSFRAME_HAS_HOOK_DATA;
|
||||
}
|
||||
|
||||
/* Version */
|
||||
|
||||
JSVersion callerVersion() const {
|
||||
return callerVersion_;
|
||||
}
|
||||
|
||||
void setCallerVersion(JSVersion version) {
|
||||
callerVersion_ = version;
|
||||
}
|
||||
|
||||
/* Return value */
|
||||
|
||||
const js::Value& returnValue() {
|
||||
|
@ -740,10 +729,6 @@ struct JSStackFrame
|
|||
return offsetof(JSStackFrame, ncode_);
|
||||
}
|
||||
|
||||
static size_t offsetOfCallerVersion() {
|
||||
return offsetof(JSStackFrame, callerVersion_);
|
||||
}
|
||||
|
||||
static size_t offsetOfBlockChain() {
|
||||
return offsetof(JSStackFrame, blockChain_);
|
||||
}
|
||||
|
|
|
@ -113,7 +113,6 @@ JSStackFrame::initCallFrameLatePrologue()
|
|||
{
|
||||
rval_.setUndefined();
|
||||
blockChain_ = NULL;
|
||||
callerVersion_ = prev_->callerVersion_; // WRONG
|
||||
|
||||
SetValueRangeToUndefined(slots(), script()->nfixed);
|
||||
}
|
||||
|
|
|
@ -1168,10 +1168,11 @@ obj_eval(JSContext *cx, uintN argc, Value *vp)
|
|||
JSScript **scriptp = bucket;
|
||||
|
||||
EVAL_CACHE_METER(probe);
|
||||
JSVersion version = cx->findVersion();
|
||||
while ((script = *scriptp) != NULL) {
|
||||
if (script->savedCallerFun &&
|
||||
script->staticLevel == staticLevel &&
|
||||
script->version == cx->version &&
|
||||
script->version == version &&
|
||||
(script->principals == principals ||
|
||||
(principals->subsume(principals, script->principals) &&
|
||||
script->principals->subsume(script->principals, principals)))) {
|
||||
|
|
|
@ -193,9 +193,10 @@ Parser::init(const jschar *base, size_t length,
|
|||
FILE *fp, const char *filename, uintN lineno)
|
||||
{
|
||||
JSContext *cx = context;
|
||||
|
||||
version = cx->findVersion();
|
||||
|
||||
tempPoolMark = JS_ARENA_MARK(&cx->tempPool);
|
||||
if (!tokenStream.init(base, length, fp, filename, lineno)) {
|
||||
if (!tokenStream.init(version, base, length, fp, filename, lineno)) {
|
||||
JS_ARENA_RELEASE(&cx->tempPool, tempPoolMark);
|
||||
return false;
|
||||
}
|
||||
|
@ -4921,7 +4922,7 @@ Parser::statement()
|
|||
PopStatement(tc);
|
||||
pn->pn_pos.end = pn2->pn_pos.end;
|
||||
pn->pn_right = pn2;
|
||||
if (JSVERSION_NUMBER(context) != JSVERSION_ECMA_3) {
|
||||
if (VersionNumber(version) != JSVERSION_ECMA_3) {
|
||||
/*
|
||||
* All legacy and extended versions must do automatic semicolon
|
||||
* insertion after do-while. See the testcase and discussion in
|
||||
|
@ -5024,7 +5025,7 @@ Parser::statement()
|
|||
if (TokenKindIsDecl(tt)
|
||||
? (pn1->pn_count > 1 || pn1->pn_op == JSOP_DEFCONST
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
|| (JSVERSION_NUMBER(context) == JSVERSION_1_7 &&
|
||||
|| (VersionNumber(version) == JSVERSION_1_7 &&
|
||||
pn->pn_op == JSOP_ITER &&
|
||||
!(pn->pn_iflags & JSITER_FOREACH) &&
|
||||
(pn1->pn_head->pn_type == TOK_RC ||
|
||||
|
@ -5038,7 +5039,7 @@ Parser::statement()
|
|||
: (pn1->pn_type != TOK_NAME &&
|
||||
pn1->pn_type != TOK_DOT &&
|
||||
#if JS_HAS_DESTRUCTURING
|
||||
((JSVERSION_NUMBER(context) == JSVERSION_1_7 &&
|
||||
((VersionNumber(version) == JSVERSION_1_7 &&
|
||||
pn->pn_op == JSOP_ITER &&
|
||||
!(pn->pn_iflags & JSITER_FOREACH))
|
||||
? (pn1->pn_type != TOK_RB || pn1->pn_count != 2)
|
||||
|
@ -5175,7 +5176,7 @@ Parser::statement()
|
|||
if (pn1 == pn2 && !CheckDestructuring(context, NULL, pn2, NULL, tc))
|
||||
return NULL;
|
||||
|
||||
if (JSVERSION_NUMBER(context) == JSVERSION_1_7) {
|
||||
if (VersionNumber(version) == JSVERSION_1_7) {
|
||||
/*
|
||||
* Destructuring for-in requires [key, value] enumeration
|
||||
* in JS1.7.
|
||||
|
@ -6878,7 +6879,7 @@ Parser::comprehensionTail(JSParseNode *kid, uintN blockid,
|
|||
if (!CheckDestructuring(context, &data, pn3, NULL, tc))
|
||||
return NULL;
|
||||
|
||||
if (JSVERSION_NUMBER(context) == JSVERSION_1_7) {
|
||||
if (VersionNumber(version) == JSVERSION_1_7) {
|
||||
/* Destructuring requires [key, value] enumeration in JS1.7. */
|
||||
if (pn3->pn_type != TOK_RB || pn3->pn_count != 2) {
|
||||
reportErrorNumber(NULL, JSREPORT_ERROR, JSMSG_BAD_FOR_LEFTSIDE);
|
||||
|
@ -7896,8 +7897,16 @@ Parser::xmlElementOrListRoot(JSBool allowList)
|
|||
* that don't recognize <script>).
|
||||
*/
|
||||
oldopts = JS_SetOptions(context, context->options | JSOPTION_XML);
|
||||
version = context->findVersion();
|
||||
tokenStream.setVersion(version);
|
||||
JS_ASSERT(VersionHasXML(version));
|
||||
|
||||
pn = xmlElementOrList(allowList);
|
||||
|
||||
JS_SetOptions(context, oldopts);
|
||||
version = context->findVersion();
|
||||
tokenStream.setVersion(version);
|
||||
JS_ASSERT(!!(oldopts & JSOPTION_XML) == VersionHasXML(version));
|
||||
return pn;
|
||||
}
|
||||
|
||||
|
|
|
@ -994,6 +994,7 @@ struct Parser : private js::AutoGCRooter
|
|||
uint32 functionCount; /* number of functions in current unit */
|
||||
JSObjectBox *traceListHead; /* list of parsed object for GC tracing */
|
||||
JSTreeContext *tc; /* innermost tree context (stack-allocated) */
|
||||
JSVersion version; /* cached version to avoid repeated lookups */
|
||||
|
||||
/* Root atoms and objects allocated for the parsed tree. */
|
||||
js::AutoKeepAtoms keepAtoms;
|
||||
|
|
|
@ -185,15 +185,16 @@ TokenStream::TokenStream(JSContext *cx)
|
|||
#endif
|
||||
|
||||
bool
|
||||
TokenStream::init(const jschar *base, size_t length, FILE *fp, const char *fn, uintN ln)
|
||||
TokenStream::init(JSVersion version, const jschar *base, size_t length, FILE *fp,
|
||||
const char *fn, uintN ln)
|
||||
{
|
||||
jschar *buf;
|
||||
|
||||
this->version = version;
|
||||
JS_ASSERT_IF(fp, !base);
|
||||
JS_ASSERT_IF(!base, length == 0);
|
||||
size_t nb = fp
|
||||
? (UNGET_LIMIT + 2 * LINE_LIMIT) * sizeof(jschar) /* see below */
|
||||
: (UNGET_LIMIT + 1 * LINE_LIMIT) * sizeof(jschar);
|
||||
jschar *buf;
|
||||
JS_ARENA_ALLOCATE_CAST(buf, jschar *, &cx->tempPool, nb);
|
||||
if (!buf) {
|
||||
js_ReportOutOfScriptQuota(cx);
|
||||
|
@ -1102,7 +1103,7 @@ TokenStream::getTokenInternal()
|
|||
JSMSG_RESERVED_ID, kw->chars)) {
|
||||
goto error;
|
||||
}
|
||||
} else if (kw->version <= JSVERSION_NUMBER(cx)) {
|
||||
} else if (kw->version <= VersionNumber(version)) {
|
||||
tt = kw->tokentype;
|
||||
tp->t_op = (JSOp) kw->op;
|
||||
goto out;
|
||||
|
@ -1438,7 +1439,7 @@ TokenStream::getTokenInternal()
|
|||
* The check for this is in jsparse.cpp, Compiler::compileScript.
|
||||
*/
|
||||
if ((flags & TSF_OPERAND) &&
|
||||
(JS_HAS_XML_OPTION(cx) || peekChar() != '!')) {
|
||||
(VersionHasXML(version) || peekChar() != '!')) {
|
||||
/* Check for XML comment or CDATA section. */
|
||||
if (matchChar('!')) {
|
||||
tokenbuf.clear();
|
||||
|
|
|
@ -320,7 +320,8 @@ class TokenStream
|
|||
* Create a new token stream, either from an input buffer or from a file.
|
||||
* Return false on file-open or memory-allocation failure.
|
||||
*/
|
||||
bool init(const jschar *base, size_t length, FILE *fp, const char *filename, uintN lineno);
|
||||
bool init(JSVersion version, const jschar *base, size_t length, FILE *fp,
|
||||
const char *filename, uintN lineno);
|
||||
void close();
|
||||
~TokenStream() {}
|
||||
|
||||
|
@ -441,6 +442,8 @@ class TokenStream
|
|||
return JS_FALSE;
|
||||
}
|
||||
|
||||
void setVersion(JSVersion newVersion) { version = newVersion; }
|
||||
|
||||
private:
|
||||
typedef struct TokenBuf {
|
||||
jschar *base; /* base of line or stream buffer */
|
||||
|
@ -511,6 +514,7 @@ class TokenStream
|
|||
JSCharBuffer tokenbuf; /* current token string buffer */
|
||||
bool maybeEOL[256]; /* probabilistic EOL lookup table */
|
||||
bool maybeStrSpecial[256];/* speeds up string scanning */
|
||||
JSVersion version; /* cached version number for scan */
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
|
|
@ -163,7 +163,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript,
|
|||
if (!script)
|
||||
return JS_FALSE;
|
||||
|
||||
script->version = JSVERSION_DEFAULT;
|
||||
script->setVersion(JSVERSION_DEFAULT);
|
||||
script->noScriptRval = true;
|
||||
script->code[0] = JSOP_STOP;
|
||||
script->code[1] = SRC_NULL;
|
||||
|
@ -177,8 +177,8 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript,
|
|||
|
||||
if (xdr->mode == JSXDR_ENCODE) {
|
||||
prologLength = script->main - script->code;
|
||||
JS_ASSERT((int16)script->version != JSVERSION_UNKNOWN);
|
||||
version = (uint32)script->version | (script->nfixed << 16);
|
||||
JS_ASSERT(script->getVersion() != JSVERSION_UNKNOWN);
|
||||
version = (uint32)script->getVersion() | (script->nfixed << 16);
|
||||
lineno = (uint32)script->lineno;
|
||||
nslots = (uint32)script->nslots;
|
||||
nslots = (uint32)((script->staticLevel << 16) | script->nslots);
|
||||
|
@ -236,7 +236,7 @@ js_XDRScript(JSXDRState *xdr, JSScript **scriptp, bool needMutableScript,
|
|||
return JS_FALSE;
|
||||
|
||||
script->main += prologLength;
|
||||
script->version = JSVersion(version & 0xffff);
|
||||
script->setVersion(JSVersion(version & 0xffff));
|
||||
script->nfixed = uint16(version >> 16);
|
||||
|
||||
/* If we know nsrcnotes, we allocated space for notes in script. */
|
||||
|
@ -881,7 +881,7 @@ js_NewScript(JSContext *cx, uint32 length, uint32 nsrcnotes, uint32 natoms,
|
|||
|
||||
PodZero(script);
|
||||
script->length = length;
|
||||
script->version = cx->version;
|
||||
script->setVersion(cx->findVersion());
|
||||
|
||||
cursor = (uint8 *)script + sizeof(JSScript);
|
||||
if (nobjects != 0) {
|
||||
|
|
|
@ -326,6 +326,15 @@ struct JSScript {
|
|||
return getAtom(arr->vector[index].atomIndex);
|
||||
}
|
||||
|
||||
JSVersion getVersion() const {
|
||||
return JSVersion(version);
|
||||
}
|
||||
|
||||
void setVersion(JSVersion newVersion) {
|
||||
JS_ASSERT((newVersion & JS_BITMASK(16)) == uint32(newVersion));
|
||||
version = newVersion;
|
||||
}
|
||||
|
||||
inline JSFunction *getFunction(size_t index);
|
||||
|
||||
inline JSObject *getRegExp(size_t index);
|
||||
|
|
|
@ -5717,12 +5717,6 @@ SynthesizeFrame(JSContext* cx, const FrameInfo& fi, JSObject* callee)
|
|||
newfp->setScopeChainNoCallObj(*JSStackFrame::sInvalidScopeChain);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Note that fp->script is still the caller's script; set the callee
|
||||
* inline frame's idea of caller version from its version.
|
||||
*/
|
||||
newfp->setCallerVersion((JSVersion) fp->script()->version);
|
||||
|
||||
/* Officially push the frame. */
|
||||
stack.pushInlineFrame(cx, newscript, newfp, cx->regs);
|
||||
|
||||
|
|
|
@ -271,9 +271,6 @@ mjit::Compiler::generatePrologue()
|
|||
masm.storeValue(UndefinedValue(), Address(JSFrameReg, JSStackFrame::offsetOfReturnValue()));
|
||||
masm.storePtr(ImmPtr(NULL), Address(JSFrameReg, JSStackFrame::offsetOfBlockChain()));
|
||||
|
||||
/* :TODO: This is entirely wrong. */
|
||||
masm.store32(Imm32(cx->version), Address(JSFrameReg, JSStackFrame::offsetOfCallerVersion()));
|
||||
|
||||
/* Set cx->fp */
|
||||
masm.loadPtr(FrameAddress(offsetof(VMFrame, cx)), Registers::ReturnReg);
|
||||
|
||||
|
|
|
@ -213,8 +213,6 @@ InlineReturn(VMFrame &f, JSBool ok)
|
|||
|
||||
PutActivationObjects(cx, fp);
|
||||
|
||||
/* :TODO: version stuff */
|
||||
|
||||
if (fp->isConstructing() && fp->returnValue().isPrimitive())
|
||||
fp->setReturnValue(fp->thisValue());
|
||||
|
||||
|
@ -433,9 +431,6 @@ UncachedInlineCall(VMFrame &f, uint32 flags, void **pret, uint32 argc)
|
|||
newfp->initCallFrame(cx, callee, newfun, argc, flags);
|
||||
SetValueRangeToUndefined(newfp->slots(), newscript->nfixed);
|
||||
|
||||
/* :TODO: Switch version if currentVersion wasn't overridden. */
|
||||
newfp->setCallerVersion((JSVersion)cx->version);
|
||||
|
||||
/* Officially push the frame. */
|
||||
stack.pushInlineFrame(cx, newscript, newfp, &f.regs);
|
||||
JS_ASSERT(newfp == f.regs.fp);
|
||||
|
|
|
@ -875,6 +875,14 @@ Version(JSContext *cx, uintN argc, jsval *vp)
|
|||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
RevertVersion(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
js_RevertVersion(cx);
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Options(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
|
@ -4086,6 +4094,7 @@ Wrap(JSContext *cx, uintN argc, jsval *vp)
|
|||
/* We use a mix of JS_FS and JS_FN to test both kinds of natives. */
|
||||
static JSFunctionSpec shell_functions[] = {
|
||||
JS_FN("version", Version, 0,0),
|
||||
JS_FN("revertVersion", RevertVersion, 0,0),
|
||||
JS_FN("options", Options, 0,0),
|
||||
JS_FN("load", Load, 1,0),
|
||||
JS_FN("readline", ReadLine, 0,0),
|
||||
|
@ -4185,7 +4194,8 @@ static const char shell_help_header[] =
|
|||
"======= ===========\n";
|
||||
|
||||
static const char *const shell_help_messages[] = {
|
||||
"version([number]) Get or set JavaScript version number",
|
||||
"version([number]) Get or force a script compilation version number",
|
||||
"revertVersion() Revert previously set version number",
|
||||
"options([option ...]) Get or toggle JavaScript options",
|
||||
"load(['foo.js' ...]) Load files named by string arguments",
|
||||
"readline() Read a single line from stdin",
|
||||
|
|
|
@ -209,11 +209,11 @@ function test()
|
|||
{
|
||||
var v = version(150);
|
||||
f = new Function("return version(arguments[0])");
|
||||
version(v);
|
||||
revertVersion();
|
||||
expect(150, f());
|
||||
//expect(150, eval("f()"));
|
||||
expect(150, eval("f()"));
|
||||
expect(0, eval("f(0); f()"));
|
||||
version(v);
|
||||
revertVersion();
|
||||
}
|
||||
print("End of Tests");
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче