mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 636224 - rm cx->interpLevel and TSF_ERROR (r=brendan)
--HG-- extra : rebase_source : 682e496d3fad9454b0279aff9bfd4c1bcf50055c
This commit is contained in:
parent
a3cfafaa02
commit
f37c253b7f
@ -0,0 +1,9 @@
|
||||
var caught = false;
|
||||
try {
|
||||
Function("a, `", "");
|
||||
} catch(e) {
|
||||
assertEq(e.toString().search("SyntaxError: malformed formal parameter") == -1, true);
|
||||
assertEq(e.toString().search("SyntaxError: illegal character") == -1, false);
|
||||
caught = true;
|
||||
}
|
||||
assertEq(caught, true);
|
@ -1703,9 +1703,6 @@ struct JSContext
|
||||
/* Branch callback. */
|
||||
JSOperationCallback operationCallback;
|
||||
|
||||
/* Interpreter activation count. */
|
||||
uintN interpLevel;
|
||||
|
||||
/* Client opaque pointers. */
|
||||
void *data;
|
||||
void *data2;
|
||||
|
134
js/src/jsfun.cpp
134
js/src/jsfun.cpp
@ -2408,16 +2408,29 @@ static JSFunctionSpec function_methods[] = {
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
/*
|
||||
* Report "malformed formal parameter" iff no illegal char or similar scanner
|
||||
* error was already reported.
|
||||
*/
|
||||
static bool
|
||||
OnBadFormal(JSContext *cx, TokenKind tt)
|
||||
{
|
||||
if (tt != TOK_ERROR)
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_FORMAL);
|
||||
else
|
||||
JS_ASSERT(cx->isExceptionPending());
|
||||
return false;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
Function(JSContext *cx, uintN argc, Value *vp)
|
||||
{
|
||||
JSObject *obj = NewFunction(cx, NULL);
|
||||
if (!obj)
|
||||
return JS_FALSE;
|
||||
JS::Anchor<JSObject *> obj(NewFunction(cx, NULL));
|
||||
if (!obj.get())
|
||||
return false;
|
||||
|
||||
/* N.B. overwriting callee with return value */
|
||||
JSObject *parent = vp[0].toObject().getParent();
|
||||
vp[0].setObject(*obj);
|
||||
JSObject &callee = JS_CALLEE(cx, vp).toObject();
|
||||
JSObject &calleeParent = *callee.getParent();
|
||||
|
||||
/*
|
||||
* NB: (new Function) is not lexically closed by its caller, it's just an
|
||||
@ -2429,10 +2442,10 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
* its running context's globalObject, which might be different from the
|
||||
* top-level reachable from scopeChain (in HTML frames, e.g.).
|
||||
*/
|
||||
JSFunction *fun = js_NewFunction(cx, obj, NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
|
||||
parent, cx->runtime->atomState.anonymousAtom);
|
||||
JSFunction *fun = js_NewFunction(cx, obj.get(), NULL, 0, JSFUN_LAMBDA | JSFUN_INTERPRETED,
|
||||
&calleeParent, cx->runtime->atomState.anonymousAtom);
|
||||
if (!fun)
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Function is static and not called directly by other functions in this
|
||||
@ -2446,8 +2459,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
const char *filename;
|
||||
JSPrincipals *principals;
|
||||
if (caller) {
|
||||
JSObject *callee = &JS_CALLEE(cx, vp).toObject();
|
||||
principals = js_EvalFramePrincipals(cx, callee, caller);
|
||||
principals = js_EvalFramePrincipals(cx, &callee, caller);
|
||||
filename = js_ComputeFilename(cx, caller, principals, &lineno);
|
||||
} else {
|
||||
filename = NULL;
|
||||
@ -2456,9 +2468,9 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
}
|
||||
|
||||
/* Belt-and-braces: check that the caller has access to parent. */
|
||||
if (!js_CheckPrincipalsAccess(cx, parent, principals,
|
||||
if (!js_CheckPrincipalsAccess(cx, &calleeParent, principals,
|
||||
CLASS_ATOM(cx, Function))) {
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2466,24 +2478,22 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
* Report errors via CSP is done in the script security manager.
|
||||
* js_CheckContentSecurityPolicy is defined in jsobj.cpp
|
||||
*/
|
||||
if (!js_CheckContentSecurityPolicy(cx, parent)) {
|
||||
if (!js_CheckContentSecurityPolicy(cx, &calleeParent)) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CSP_BLOCKED_FUNCTION);
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
EmptyShape *emptyCallShape = EmptyShape::getEmptyCallShape(cx);
|
||||
if (!emptyCallShape)
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
AutoShapeRooter shapeRoot(cx, emptyCallShape);
|
||||
|
||||
Bindings bindings(cx, emptyCallShape);
|
||||
AutoBindingsRooter root(cx, bindings);
|
||||
|
||||
Value *argv = vp + 2;
|
||||
Value *argv = JS_ARGV(cx, vp);
|
||||
uintN n = argc ? argc - 1 : 0;
|
||||
if (n > 0) {
|
||||
enum { OK, BAD, BAD_FORMAL } state;
|
||||
|
||||
/*
|
||||
* Collect the function-argument arguments into one string, separated
|
||||
* by commas, then make a tokenstream from that string, and scan it to
|
||||
@ -2494,13 +2504,12 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
* compiler, but doing it this way is less of a delta from the old
|
||||
* code. See ECMA 15.3.2.1.
|
||||
*/
|
||||
state = BAD_FORMAL;
|
||||
size_t args_length = 0;
|
||||
for (uintN i = 0; i < n; i++) {
|
||||
/* Collect the lengths for all the function-argument arguments. */
|
||||
JSString *arg = js_ValueToString(cx, argv[i]);
|
||||
if (!arg)
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
argv[i].setString(arg);
|
||||
|
||||
/*
|
||||
@ -2511,7 +2520,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
args_length = old_args_length + arg->length();
|
||||
if (args_length < old_args_length) {
|
||||
js_ReportAllocationOverflow(cx);
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2521,7 +2530,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
if (args_length < old_args_length ||
|
||||
args_length >= ~(size_t)0 / sizeof(jschar)) {
|
||||
js_ReportAllocationOverflow(cx);
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2529,13 +2538,11 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
* for a terminating 0. Mark cx->tempPool for later release, to free
|
||||
* collected_args and its tokenstream in one swoop.
|
||||
*/
|
||||
void *mark = JS_ARENA_MARK(&cx->tempPool);
|
||||
jschar *cp;
|
||||
JS_ARENA_ALLOCATE_CAST(cp, jschar *, &cx->tempPool,
|
||||
(args_length+1) * sizeof(jschar));
|
||||
AutoArenaAllocator aaa(&cx->tempPool);
|
||||
jschar *cp = aaa.alloc<jschar>(args_length + 1);
|
||||
if (!cp) {
|
||||
js_ReportOutOfScriptQuota(cx);
|
||||
return JS_FALSE;
|
||||
return false;
|
||||
}
|
||||
jschar *collected_args = cp;
|
||||
|
||||
@ -2546,10 +2553,8 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
JSString *arg = argv[i].toString();
|
||||
size_t arg_length = arg->length();
|
||||
const jschar *arg_chars = arg->getChars(cx);
|
||||
if (!arg_chars) {
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!arg_chars)
|
||||
return false;
|
||||
(void) js_strncpy(cp, arg_chars, arg_length);
|
||||
cp += arg_length;
|
||||
|
||||
@ -2559,10 +2564,8 @@ 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, filename, lineno, cx->findVersion())) {
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
return JS_FALSE;
|
||||
}
|
||||
if (!ts.init(collected_args, args_length, filename, lineno, cx->findVersion()))
|
||||
return false;
|
||||
|
||||
/* The argument string may be empty or contain no tokens. */
|
||||
TokenKind tt = ts.getToken();
|
||||
@ -2573,7 +2576,7 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
* TOK_ERROR, which was already reported.
|
||||
*/
|
||||
if (tt != TOK_NAME)
|
||||
goto after_args;
|
||||
return OnBadFormal(cx, tt);
|
||||
|
||||
/*
|
||||
* Get the atom corresponding to the name from the token
|
||||
@ -2585,23 +2588,18 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
/* Check for a duplicate parameter name. */
|
||||
if (bindings.hasBinding(cx, atom)) {
|
||||
JSAutoByteString name;
|
||||
if (!js_AtomToPrintableString(cx, atom, &name)) {
|
||||
state = BAD;
|
||||
goto after_args;
|
||||
}
|
||||
if (!js_AtomToPrintableString(cx, atom, &name))
|
||||
return false;
|
||||
if (!ReportCompileErrorNumber(cx, &ts, NULL,
|
||||
JSREPORT_WARNING | JSREPORT_STRICT,
|
||||
JSMSG_DUPLICATE_FORMAL, name.ptr())) {
|
||||
state = BAD;
|
||||
goto after_args;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16 dummy;
|
||||
if (!bindings.addArgument(cx, atom, &dummy)) {
|
||||
state = BAD;
|
||||
goto after_args;
|
||||
}
|
||||
if (!bindings.addArgument(cx, atom, &dummy))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Get the next token. Stop on end of stream. Otherwise
|
||||
@ -2611,44 +2609,32 @@ Function(JSContext *cx, uintN argc, Value *vp)
|
||||
if (tt == TOK_EOF)
|
||||
break;
|
||||
if (tt != TOK_COMMA)
|
||||
goto after_args;
|
||||
return OnBadFormal(cx, tt);
|
||||
tt = ts.getToken();
|
||||
}
|
||||
}
|
||||
|
||||
state = OK;
|
||||
after_args:
|
||||
if (state == BAD_FORMAL && !ts.isError()) {
|
||||
/*
|
||||
* Report "malformed formal parameter" iff no illegal char or
|
||||
* similar scanner error was already reported.
|
||||
*/
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
|
||||
JSMSG_BAD_FORMAL);
|
||||
}
|
||||
ts.close();
|
||||
JS_ARENA_RELEASE(&cx->tempPool, mark);
|
||||
if (state != OK)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
JSString *str;
|
||||
JS::Anchor<JSString *> strAnchor(NULL);
|
||||
const jschar *chars;
|
||||
size_t length;
|
||||
|
||||
if (argc) {
|
||||
str = js_ValueToString(cx, argv[argc - 1]);
|
||||
JSString *str = js_ValueToString(cx, argv[argc - 1]);
|
||||
if (!str)
|
||||
return JS_FALSE;
|
||||
argv[argc - 1].setString(str);
|
||||
return false;
|
||||
strAnchor.set(str);
|
||||
chars = str->getChars(cx);
|
||||
length = str->length();
|
||||
} else {
|
||||
str = cx->runtime->emptyString;
|
||||
chars = cx->runtime->emptyString->chars();
|
||||
length = 0;
|
||||
}
|
||||
|
||||
size_t length = str->length();
|
||||
const jschar *chars = str->getChars(cx);
|
||||
if (!chars)
|
||||
return JS_FALSE;
|
||||
|
||||
JS_SET_RVAL(cx, vp, ObjectValue(*obj.get()));
|
||||
return Compiler::compileFunctionBody(cx, fun, principals, &bindings,
|
||||
chars, length, filename, lineno, cx->findVersion());
|
||||
chars, length, filename, lineno,
|
||||
cx->findVersion());
|
||||
}
|
||||
|
||||
namespace js {
|
||||
|
@ -614,8 +614,6 @@ RunScript(JSContext *cx, JSScript *script, JSStackFrame *fp)
|
||||
JMCheckLogging();
|
||||
#endif
|
||||
|
||||
AutoInterpPreparer prepareInterp(cx, script);
|
||||
|
||||
/* FIXME: Once bug 470510 is fixed, make this an assert. */
|
||||
if (script->compileAndGo) {
|
||||
int32 flags = fp->scopeChain().getGlobal()->getReservedSlot(JSRESERVED_GLOBAL_FLAGS).toInt32();
|
||||
@ -2461,10 +2459,8 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte
|
||||
InterpExitGuard(JSContext *cx, JSFrameRegs ®s)
|
||||
: cx(cx), regs(regs), prevContextRegs(cx->regs) {
|
||||
cx->setCurrentRegs(®s);
|
||||
++cx->interpLevel;
|
||||
}
|
||||
~InterpExitGuard() {
|
||||
--cx->interpLevel;
|
||||
JS_ASSERT(cx->regs == ®s);
|
||||
*prevContextRegs = regs;
|
||||
cx->setCurrentRegs(prevContextRegs);
|
||||
|
@ -515,22 +515,6 @@ class AutoPreserveEnumerators {
|
||||
}
|
||||
};
|
||||
|
||||
struct AutoInterpPreparer {
|
||||
JSContext *cx;
|
||||
JSScript *script;
|
||||
|
||||
AutoInterpPreparer(JSContext *cx, JSScript *script)
|
||||
: cx(cx), script(script)
|
||||
{
|
||||
cx->interpLevel++;
|
||||
}
|
||||
|
||||
~AutoInterpPreparer()
|
||||
{
|
||||
--cx->interpLevel;
|
||||
}
|
||||
};
|
||||
|
||||
class InvokeSessionGuard
|
||||
{
|
||||
InvokeArgsGuard args_;
|
||||
@ -601,7 +585,6 @@ InvokeSessionGuard::invoke(JSContext *cx) const
|
||||
AutoPreserveEnumerators preserve(cx);
|
||||
Probes::enterJSFun(cx, fp->fun(), script_);
|
||||
#ifdef JS_METHODJIT
|
||||
AutoInterpPreparer prepareInterp(cx, script_);
|
||||
ok = mjit::EnterMethodJIT(cx, fp, code, stackLimit_);
|
||||
cx->regs->pc = stop_;
|
||||
#else
|
||||
|
@ -225,7 +225,6 @@ Parser::~Parser()
|
||||
|
||||
if (principals)
|
||||
JSPRINCIPALS_DROP(cx, principals);
|
||||
tokenStream.close();
|
||||
JS_ARENA_RELEASE(&cx->tempPool, tempPoolMark);
|
||||
}
|
||||
|
||||
|
@ -227,8 +227,7 @@ TokenStream::init(const jschar *base, size_t length, const char *fn, uintN ln, J
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TokenStream::close()
|
||||
TokenStream::~TokenStream()
|
||||
{
|
||||
if (flags & TSF_OWNFILENAME)
|
||||
cx->free((void *) filename);
|
||||
@ -432,7 +431,6 @@ TokenStream::reportCompileErrorNumberVA(JSParseNode *pn, uintN flags, uintN erro
|
||||
JSBool ok;
|
||||
const TokenPos *tp;
|
||||
uintN i;
|
||||
JSErrorReporter onError;
|
||||
|
||||
if (JSREPORT_IS_STRICT(flags) && !cx->hasStrictOption())
|
||||
return JS_TRUE;
|
||||
@ -512,45 +510,20 @@ TokenStream::reportCompileErrorNumberVA(JSParseNode *pn, uintN flags, uintN erro
|
||||
* as the non-top-level "load", "eval", or "compile" native function
|
||||
* returns false, the top-level reporter will eventually receive the
|
||||
* uncaught exception report.
|
||||
*
|
||||
* XXX it'd probably be best if there was only one call to this
|
||||
* function, but there seem to be two error reporter call points.
|
||||
*/
|
||||
onError = cx->errorReporter;
|
||||
|
||||
/*
|
||||
* Try to raise an exception only if there isn't one already set --
|
||||
* otherwise the exception will describe the last compile-time error,
|
||||
* which is likely spurious.
|
||||
*/
|
||||
if (!(flags & TSF_ERROR)) {
|
||||
if (js_ErrorToException(cx, message, &report, NULL, NULL))
|
||||
onError = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Suppress any compile-time errors that don't occur at the top level.
|
||||
* This may still fail, as interplevel may be zero in contexts where we
|
||||
* don't really want to call the error reporter, as when js is called
|
||||
* by other code which could catch the error.
|
||||
*/
|
||||
if (cx->interpLevel != 0 && !JSREPORT_IS_WARNING(flags))
|
||||
onError = NULL;
|
||||
|
||||
if (onError) {
|
||||
JSDebugErrorHook hook = cx->debugHooks->debugErrorHook;
|
||||
|
||||
if (!js_ErrorToException(cx, message, &report, NULL, NULL)) {
|
||||
/*
|
||||
* If debugErrorHook is present then we give it a chance to veto
|
||||
* sending the error on to the regular error reporter.
|
||||
*/
|
||||
if (hook && !hook(cx, message, &report,
|
||||
cx->debugHooks->debugErrorHookData)) {
|
||||
onError = NULL;
|
||||
}
|
||||
bool reportError = true;
|
||||
if (JSDebugErrorHook hook = cx->debugHooks->debugErrorHook)
|
||||
reportError = hook(cx, message, &report, cx->debugHooks->debugErrorHookData);
|
||||
|
||||
/* Report the error */
|
||||
if (reportError && cx->errorReporter)
|
||||
cx->errorReporter(cx, message, &report);
|
||||
}
|
||||
if (onError)
|
||||
(*onError)(cx, message, &report);
|
||||
|
||||
out:
|
||||
if (linebytes)
|
||||
@ -571,11 +544,6 @@ TokenStream::reportCompileErrorNumberVA(JSParseNode *pn, uintN flags, uintN erro
|
||||
cx->free((void *)report.messageArgs);
|
||||
}
|
||||
|
||||
if (!JSREPORT_IS_WARNING(flags)) {
|
||||
/* Set the error flag to suppress spurious reports. */
|
||||
flags |= TSF_ERROR;
|
||||
}
|
||||
|
||||
return warning;
|
||||
}
|
||||
|
||||
@ -1899,13 +1867,14 @@ TokenStream::getTokenInternal()
|
||||
return tt;
|
||||
|
||||
error:
|
||||
JS_ASSERT(cx->isExceptionPending());
|
||||
|
||||
/*
|
||||
* For erroneous multi-line tokens we won't have changed end.lineno (it'll
|
||||
* still be equal to begin.lineno) so we revert end.index to be equal to
|
||||
* begin.index + 1 (as if it's a 1-char token) to avoid having inconsistent
|
||||
* begin/end positions. end.index isn't used in error messages anyway.
|
||||
*/
|
||||
flags |= TSF_ERROR;
|
||||
flags |= TSF_DIRTYLINE;
|
||||
tp->pos.end.index = tp->pos.begin.index + 1;
|
||||
tp->type = TOK_ERROR;
|
||||
|
@ -252,7 +252,6 @@ struct Token {
|
||||
|
||||
enum TokenStreamFlags
|
||||
{
|
||||
TSF_ERROR = 0x01, /* fatal error while compiling */
|
||||
TSF_EOF = 0x02, /* hit end of file */
|
||||
TSF_EOL = 0x04, /* an EOL was hit in whitespace or a multi-line comment */
|
||||
TSF_OPERAND = 0x08, /* looking for operand, not operator */
|
||||
@ -327,8 +326,7 @@ class TokenStream
|
||||
*/
|
||||
bool init(const jschar *base, size_t length, const char *filename, uintN lineno,
|
||||
JSVersion version);
|
||||
void close();
|
||||
~TokenStream() {}
|
||||
~TokenStream();
|
||||
|
||||
/* Accessors. */
|
||||
JSContext *getContext() const { return cx; }
|
||||
@ -363,7 +361,6 @@ class TokenStream
|
||||
bool isXMLOnlyMode() { return !!(flags & TSF_XMLONLYMODE); }
|
||||
bool isUnexpectedEOF() { return !!(flags & TSF_UNEXPECTED_EOF); }
|
||||
bool isEOF() const { return !!(flags & TSF_EOF); }
|
||||
bool isError() const { return !!(flags & TSF_ERROR); }
|
||||
bool hasOctalCharacterEscape() const { return flags & TSF_OCTAL_CHAR; }
|
||||
|
||||
/* Mutators. */
|
||||
@ -418,8 +415,6 @@ class TokenStream
|
||||
return tt;
|
||||
}
|
||||
|
||||
JS_ASSERT(!(flags & TSF_ERROR));
|
||||
|
||||
return getTokenInternal();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user