mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 10:00:54 +00:00
Merge tracemonkey to mozilla-central. a=blockers
This commit is contained in:
commit
954ddf8007
12
js/src/jit-test/tests/basic/testBug634590.js
Normal file
12
js/src/jit-test/tests/basic/testBug634590.js
Normal file
@ -0,0 +1,12 @@
|
||||
this.name = "outer";
|
||||
var sb = evalcx('');
|
||||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
function f() { return this.name; }
|
||||
assertEq(evalcx('this.f = parent.f;\n' +
|
||||
'var s = "";\n' +
|
||||
'for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f();\n' +
|
||||
's',
|
||||
sb),
|
||||
"innerinnerinnerinnerinnerinnerinnerinnerinnerinner");
|
19
js/src/jit-test/tests/basic/testBug634590b.js
Normal file
19
js/src/jit-test/tests/basic/testBug634590b.js
Normal file
@ -0,0 +1,19 @@
|
||||
this.name = "outer";
|
||||
var sb = evalcx('');
|
||||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
function f() { return this.name; }
|
||||
f.notMuchTodo = '42';
|
||||
assertEq(evalcx('{\n' +
|
||||
' let f = parent.f;\n' +
|
||||
' let name = "block";\n' +
|
||||
' (function () {\n' +
|
||||
' eval(f.notMuchTodo);\n' + // reify Block
|
||||
' var s = "";\n' +
|
||||
' for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f();\n' +
|
||||
' return s;\n' +
|
||||
' })();\n' +
|
||||
'}',
|
||||
sb),
|
||||
"outerouterouterouterouterouterouterouterouterouter");
|
20
js/src/jit-test/tests/basic/testBug634590c.js
Normal file
20
js/src/jit-test/tests/basic/testBug634590c.js
Normal file
@ -0,0 +1,20 @@
|
||||
this.name = "outer";
|
||||
var sb = evalcx('');
|
||||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
function f() { return this.name; }
|
||||
f.notMuchTodo = '42';
|
||||
assertEq(evalcx('(function () {\n' +
|
||||
' arguments = null;\n' + // force heavyweight
|
||||
' var f = parent.f;\n' +
|
||||
' var name = "call";\n' +
|
||||
' return (function () {\n' +
|
||||
' eval(f.notMuchTodo);\n' + // reify Call, make f() compile to JSOP_CALLNAME
|
||||
' var s = "";\n' +
|
||||
' for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f();\n' +
|
||||
' return s;\n' +
|
||||
' })();\n' +
|
||||
'})()',
|
||||
sb),
|
||||
"outerouterouterouterouterouterouterouterouterouter");
|
19
js/src/jit-test/tests/basic/testBug634590d.js
Normal file
19
js/src/jit-test/tests/basic/testBug634590d.js
Normal file
@ -0,0 +1,19 @@
|
||||
this.name = "outer";
|
||||
var sb = evalcx('');
|
||||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
this.f = function name(outer) {
|
||||
if (outer) {
|
||||
return function () {
|
||||
return name(false);
|
||||
}();
|
||||
}
|
||||
return this.name;
|
||||
}
|
||||
assertEq(evalcx('this.f = parent.f;\n' +
|
||||
'var s = "";\n' +
|
||||
'for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f(true);\n' +
|
||||
's',
|
||||
sb),
|
||||
"outerouterouterouterouterouterouterouterouterouter");
|
@ -463,12 +463,12 @@ JSCompartment::mark(JSTracer *trc)
|
||||
{
|
||||
if (IS_GC_MARKING_TRACER(trc)) {
|
||||
JSRuntime *rt = trc->context->runtime;
|
||||
if (rt->gcCurrentCompartment != NULL && rt->gcCurrentCompartment != this)
|
||||
|
||||
if (rt->gcCurrentCompartment && rt->gcCurrentCompartment != this)
|
||||
return;
|
||||
|
||||
|
||||
if (marked)
|
||||
return;
|
||||
|
||||
marked = true;
|
||||
}
|
||||
|
||||
|
@ -449,7 +449,7 @@ struct JS_FRIEND_API(JSCompartment) {
|
||||
|
||||
bool init();
|
||||
|
||||
/* Mark cross-compartment pointers. */
|
||||
/* Mark cross-compartment wrappers. */
|
||||
void markCrossCompartment(JSTracer *trc);
|
||||
|
||||
/* Mark this compartment's local roots. */
|
||||
|
@ -778,7 +778,6 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, Value *vp)
|
||||
if (!ok)
|
||||
goto out;
|
||||
shape = obj->nativeLookup(propid);
|
||||
JS_ASSERT_IF(!shape, !wp->setter);
|
||||
|
||||
if (!shape) {
|
||||
ok = true;
|
||||
|
@ -2668,7 +2668,7 @@ LookupInterpretedFunctionPrototype(JSContext *cx, JSObject *funobj)
|
||||
return shape;
|
||||
}
|
||||
|
||||
}
|
||||
} /* namespace js */
|
||||
|
||||
static JSBool
|
||||
ThrowTypeError(JSContext *cx, uintN argc, Value *vp)
|
||||
|
@ -2189,9 +2189,12 @@ SweepCompartments(JSContext *cx, JSGCInvocationKind gckind)
|
||||
while (read < end) {
|
||||
JSCompartment *compartment = *read++;
|
||||
|
||||
/* Unmarked compartments containing marked objects don't get deleted, except LAST_CONTEXT GC is performed. */
|
||||
if ((!compartment->isMarked() && compartment->arenaListsAreEmpty())
|
||||
|| gckind == GC_LAST_CONTEXT)
|
||||
/*
|
||||
* Unmarked compartments containing marked objects don't get deleted,
|
||||
* except when LAST_CONTEXT GC is performed.
|
||||
*/
|
||||
if ((!compartment->isMarked() && compartment->arenaListsAreEmpty()) ||
|
||||
gckind == GC_LAST_CONTEXT)
|
||||
{
|
||||
JS_ASSERT(compartment->freeLists.isEmpty());
|
||||
if (callback)
|
||||
@ -2356,13 +2359,16 @@ MarkAndSweepCompartment(JSContext *cx, JSCompartment *comp, JSGCInvocationKind g
|
||||
comp->finalizeStringArenaLists(cx);
|
||||
TIMESTAMP(sweepStringEnd);
|
||||
|
||||
#ifdef DEBUG
|
||||
/* Make sure that we didn't mark a Shape in another compartment. */
|
||||
/*
|
||||
* Unmark all shapes. Even a per-compartment GC can mark shapes in other
|
||||
* compartments, and we need to clear these bits. See bug 635873. This will
|
||||
* be fixed in bug 569422.
|
||||
*/
|
||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
|
||||
JS_ASSERT_IF(*c != comp, (*c)->propertyTree.checkShapesAllUnmarked(cx));
|
||||
(*c)->propertyTree.unmarkShapes(cx);
|
||||
|
||||
PropertyTree::dumpShapes(cx);
|
||||
#endif
|
||||
TIMESTAMP(sweepShapeEnd);
|
||||
|
||||
/*
|
||||
* Destroy arenas after we finished the sweeping so finalizers can safely
|
||||
@ -2482,6 +2488,7 @@ MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind GCTIMER_PARAM)
|
||||
(*c)->propertyTree.sweepShapes(cx);
|
||||
|
||||
PropertyTree::dumpShapes(cx);
|
||||
TIMESTAMP(sweepShapeEnd);
|
||||
|
||||
SweepCompartments(cx, gckind);
|
||||
|
||||
@ -2721,7 +2728,7 @@ GCUntilDone(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
||||
* NULL to look for violations.
|
||||
*/
|
||||
SwitchToCompartment(cx, (JSCompartment *)NULL);
|
||||
|
||||
|
||||
JS_ASSERT(!rt->gcCurrentCompartment);
|
||||
rt->gcCurrentCompartment = comp;
|
||||
|
||||
|
@ -422,18 +422,19 @@ GCTimer::finish(bool lastGC) {
|
||||
gcFile = fopen("gcTimer.dat", "a");
|
||||
|
||||
fprintf(gcFile, " AppTime, Total, Mark, Sweep, FinObj,");
|
||||
fprintf(gcFile, " FinStr, Destroy, newChunks, destroyChunks\n");
|
||||
fprintf(gcFile, " FinStr, SwShapes, Destroy, +Chunks, -Chunks\n");
|
||||
}
|
||||
JS_ASSERT(gcFile);
|
||||
fprintf(gcFile, "%12.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %7.1f, ",
|
||||
fprintf(gcFile, "%12.1f, %6.1f, %6.1f, %6.1f, %6.1f, %6.1f, %8.1f, %6.1f, ",
|
||||
(double)(enter - getFirstEnter()) / 1e6,
|
||||
(double)(end - enter) / 1e6,
|
||||
(double)(startSweep - startMark) / 1e6,
|
||||
(double)(sweepDestroyEnd - startSweep) / 1e6,
|
||||
(double)(sweepObjectEnd - startSweep) / 1e6,
|
||||
(double)(sweepStringEnd - sweepObjectEnd) / 1e6,
|
||||
(double)(sweepDestroyEnd - sweepStringEnd) / 1e6);
|
||||
fprintf(gcFile, "%10d, %10d \n", newChunkCount,
|
||||
(double)(sweepShapeEnd - sweepStringEnd) / 1e6,
|
||||
(double)(sweepDestroyEnd - sweepShapeEnd) / 1e6);
|
||||
fprintf(gcFile, "%7d, %7d \n", newChunkCount,
|
||||
destroyChunkCount);
|
||||
fflush(gcFile);
|
||||
|
||||
|
@ -148,6 +148,7 @@ struct GCTimer {
|
||||
uint64 startSweep;
|
||||
uint64 sweepObjectEnd;
|
||||
uint64 sweepStringEnd;
|
||||
uint64 sweepShapeEnd;
|
||||
uint64 sweepDestroyEnd;
|
||||
uint64 end;
|
||||
|
||||
|
@ -2190,6 +2190,15 @@ ScriptPrologue(JSContext *cx, JSStackFrame *fp)
|
||||
|
||||
namespace js {
|
||||
|
||||
#ifdef __APPLE__
|
||||
static JS_NEVER_INLINE bool
|
||||
NEVER_INLINE_ComputeImplicitThis(JSContext *cx, JSObject *obj, const Value &funval, Value *vp)
|
||||
{
|
||||
return ComputeImplicitThis(cx, obj, funval, vp);
|
||||
}
|
||||
#define ComputeImplicitThis(cx, obj, funval, vp) NEVER_INLINE_ComputeImplicitThis(cx, obj, funval, vp)
|
||||
#endif
|
||||
|
||||
JS_REQUIRES_STACK JS_NEVER_INLINE bool
|
||||
Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInterpMode interpMode)
|
||||
{
|
||||
@ -2213,8 +2222,8 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte
|
||||
* expect from looking at the code. (We do omit POPs after SETs;
|
||||
* unfortunate, but not worth fixing.)
|
||||
*/
|
||||
# define LOG_OPCODE(OP) JS_BEGIN_MACRO \
|
||||
if (JS_UNLIKELY(cx->logfp != NULL) && \
|
||||
# define LOG_OPCODE(OP) JS_BEGIN_MACRO \
|
||||
if (JS_UNLIKELY(cx->logfp != NULL) && \
|
||||
(OP) == *regs.pc) \
|
||||
js_LogOpcode(cx); \
|
||||
JS_END_MACRO
|
||||
@ -2337,14 +2346,17 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte
|
||||
#define LOAD_DOUBLE(PCOFF, dbl) \
|
||||
(dbl = script->getConst(GET_FULL_INDEX(PCOFF)).toDouble())
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
bool useMethodJIT = cx->methodJitEnabled && interpMode == JSINTERP_NORMAL;
|
||||
#else
|
||||
bool useMethodJIT = false;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JS_METHODJIT
|
||||
|
||||
#define RESET_USE_METHODJIT() \
|
||||
JS_BEGIN_MACRO \
|
||||
useMethodJIT = cx->methodJitEnabled && \
|
||||
interpMode == JSINTERP_NORMAL && \
|
||||
script->getJITStatus(regs.fp->isConstructing()) != JITScript_Invalid; \
|
||||
JS_END_MACRO
|
||||
|
||||
#define MONITOR_BRANCH_METHODJIT() \
|
||||
JS_BEGIN_MACRO \
|
||||
mjit::CompileStatus status = \
|
||||
@ -2366,10 +2378,12 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte
|
||||
|
||||
#else
|
||||
|
||||
#define RESET_USE_METHODJIT() ((void) 0)
|
||||
|
||||
#define MONITOR_BRANCH_METHODJIT() ((void) 0)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
||||
#ifdef MOZ_TRACEVIS
|
||||
@ -2574,6 +2588,8 @@ Interpret(JSContext *cx, JSStackFrame *entryFrame, uintN inlineCallCount, JSInte
|
||||
|
||||
CHECK_INTERRUPT_HANDLER();
|
||||
|
||||
RESET_USE_METHODJIT();
|
||||
|
||||
/* State communicated between non-local jumps: */
|
||||
JSBool interpReturnOK;
|
||||
JSAtom *atomNotDefined;
|
||||
@ -2894,6 +2910,7 @@ BEGIN_CASE(JSOP_STOP)
|
||||
atoms = FrameAtomBase(cx, regs.fp);
|
||||
|
||||
/* Resume execution in the calling frame. */
|
||||
RESET_USE_METHODJIT();
|
||||
JS_ASSERT(inlineCallCount);
|
||||
inlineCallCount--;
|
||||
if (JS_LIKELY(interpReturnOK)) {
|
||||
@ -4737,6 +4754,7 @@ BEGIN_CASE(JSOP_FUNCALL)
|
||||
if (newfun->isHeavyweight() && !js_GetCallObject(cx, regs.fp))
|
||||
goto error;
|
||||
|
||||
RESET_USE_METHODJIT();
|
||||
inlineCallCount++;
|
||||
JS_RUNTIME_METER(rt, inlineCalls);
|
||||
|
||||
@ -4802,26 +4820,13 @@ BEGIN_CASE(JSOP_SETCALL)
|
||||
}
|
||||
END_CASE(JSOP_SETCALL)
|
||||
|
||||
#define SLOW_PUSH_THISV(cx, obj) \
|
||||
JS_BEGIN_MACRO \
|
||||
Class *clasp; \
|
||||
JSObject *thisp = obj; \
|
||||
if (!thisp->getParent() || \
|
||||
(clasp = thisp->getClass()) == &js_CallClass || \
|
||||
clasp == &js_BlockClass || \
|
||||
clasp == &js_DeclEnvClass) { \
|
||||
/* Push the ImplicitThisValue for the Environment Record */ \
|
||||
/* associated with obj. See ES5 sections 10.2.1.1.6 and */ \
|
||||
/* 10.2.1.2.6 (ImplicitThisValue) and section 11.2.3 */ \
|
||||
/* (Function Calls). */ \
|
||||
PUSH_UNDEFINED(); \
|
||||
} else { \
|
||||
thisp = thisp->thisObject(cx); \
|
||||
if (!thisp) \
|
||||
goto error; \
|
||||
PUSH_OBJECT(*thisp); \
|
||||
} \
|
||||
JS_END_MACRO
|
||||
#define PUSH_IMPLICIT_THIS(cx, obj, funval) \
|
||||
JS_BEGIN_MACRO \
|
||||
Value v; \
|
||||
if (!ComputeImplicitThis(cx, obj, funval, &v)) \
|
||||
goto error; \
|
||||
PUSH_COPY(v); \
|
||||
JS_END_MACRO \
|
||||
|
||||
BEGIN_CASE(JSOP_GETGNAME)
|
||||
BEGIN_CASE(JSOP_CALLGNAME)
|
||||
@ -4851,20 +4856,9 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
PUSH_COPY(rval);
|
||||
}
|
||||
|
||||
/*
|
||||
* Push results, the same as below, but with a prop$ hit there
|
||||
* is no need to test for the unusual and uncacheable case where
|
||||
* the caller determines |this|.
|
||||
*/
|
||||
#if DEBUG
|
||||
Class *clasp;
|
||||
JS_ASSERT(!obj->getParent() ||
|
||||
(clasp = obj->getClass()) == &js_CallClass ||
|
||||
clasp == &js_BlockClass ||
|
||||
clasp == &js_DeclEnvClass);
|
||||
#endif
|
||||
JS_ASSERT(obj->isGlobal() || IsCacheableNonGlobalScope(obj));
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
|
||||
PUSH_UNDEFINED();
|
||||
PUSH_IMPLICIT_THIS(cx, obj, regs.sp[-1]);
|
||||
len = JSOP_NAME_LENGTH;
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
@ -4902,7 +4896,7 @@ BEGIN_CASE(JSOP_CALLNAME)
|
||||
|
||||
/* obj must be on the scope chain, thus not a function. */
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
|
||||
SLOW_PUSH_THISV(cx, obj);
|
||||
PUSH_IMPLICIT_THIS(cx, obj, rval);
|
||||
}
|
||||
END_CASE(JSOP_NAME)
|
||||
|
||||
@ -6405,7 +6399,7 @@ BEGIN_CASE(JSOP_XMLNAME)
|
||||
goto error;
|
||||
regs.sp[-1] = rval;
|
||||
if (op == JSOP_CALLXMLNAME)
|
||||
SLOW_PUSH_THISV(cx, obj);
|
||||
PUSH_IMPLICIT_THIS(cx, obj, rval);
|
||||
}
|
||||
END_CASE(JSOP_XMLNAME)
|
||||
|
||||
|
@ -479,7 +479,7 @@ JSStackFrame::callObj() const
|
||||
JS_ASSERT(hasCallObj());
|
||||
JSObject *pobj = &scopeChain();
|
||||
while (JS_UNLIKELY(pobj->getClass() != &js_CallClass)) {
|
||||
JS_ASSERT(js_IsCacheableNonGlobalScope(pobj) || pobj->isWith());
|
||||
JS_ASSERT(js::IsCacheableNonGlobalScope(pobj) || pobj->isWith());
|
||||
pobj = pobj->getParent();
|
||||
}
|
||||
return *pobj;
|
||||
@ -666,6 +666,83 @@ class PrimitiveBehavior<double> {
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/*
|
||||
* Compute the implicit |this| parameter for a call expression where the callee
|
||||
* is an unqualified name reference.
|
||||
*
|
||||
* We can avoid computing |this| eagerly and push the implicit callee-coerced
|
||||
* |this| value, undefined, according to this decision tree:
|
||||
*
|
||||
* 1. If the called value, funval, is not an object, bind |this| to undefined.
|
||||
*
|
||||
* 2. The nominal |this|, obj, has one of Block, Call, or DeclEnv class (this
|
||||
* is what IsCacheableNonGlobalScope tests). Such objects-as-scopes must be
|
||||
* censored.
|
||||
*
|
||||
* 3. obj is a global. There are several sub-cases:
|
||||
*
|
||||
* a) obj is a proxy: we try unwrapping it (see jswrapper.cpp) in order to find
|
||||
* a function object inside. If the proxy is not a wrapper, or else it wraps
|
||||
* a non-function, then bind |this| to undefined per ES5-strict/Harmony.
|
||||
*
|
||||
* [Else fall through with callee pointing to an unwrapped function object.]
|
||||
*
|
||||
* b) If callee is a function (after unwrapping if necessary), check whether it
|
||||
* is interpreted and in strict mode. If so, then bind |this| to undefined
|
||||
* per ES5 strict.
|
||||
*
|
||||
* c) Now check that callee is scoped by the same global object as the object
|
||||
* in which its unqualified name was bound as a property. ES1-3 bound |this|
|
||||
* to the name's "Reference base object", which in the context of multiple
|
||||
* global objects may not be the callee's global. If globals match, bind
|
||||
* |this| to undefined.
|
||||
*
|
||||
* This is a backward compatibility measure; see bug 634590.
|
||||
*
|
||||
* 4. Finally, obj is neither a declarative scope object to be censored, nor a
|
||||
* global where the callee requires no backward-compatible special handling
|
||||
* or future-proofing based on (explicit or imputed by Harmony status in the
|
||||
* proxy case) strict mode opt-in. Bind |this| to obj->thisObject().
|
||||
*
|
||||
* We set *vp to undefined early to reduce code size and bias this code for the
|
||||
* common and future-friendly cases.
|
||||
*/
|
||||
inline bool
|
||||
ComputeImplicitThis(JSContext *cx, JSObject *obj, const Value &funval, Value *vp)
|
||||
{
|
||||
vp->setUndefined();
|
||||
|
||||
if (!funval.isObject())
|
||||
return true;
|
||||
|
||||
if (!obj->isGlobal()) {
|
||||
if (IsCacheableNonGlobalScope(obj))
|
||||
return true;
|
||||
} else {
|
||||
JSObject *callee = &funval.toObject();
|
||||
|
||||
if (callee->isProxy()) {
|
||||
callee = callee->unwrap();
|
||||
if (!callee->isFunction())
|
||||
return true; // treat any non-wrapped-function proxy as strict
|
||||
}
|
||||
if (callee->isFunction()) {
|
||||
JSFunction *fun = callee->getFunctionPrivate();
|
||||
if (fun->isInterpreted() && fun->inStrictMode())
|
||||
return true;
|
||||
}
|
||||
if (callee->getGlobal() == cx->fp()->scopeChain().getGlobal())
|
||||
return true;;
|
||||
}
|
||||
|
||||
obj = obj->thisObject(cx);
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
vp->setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
GetPrimitiveThis(JSContext *cx, Value *vp, T *v)
|
||||
|
@ -5052,7 +5052,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult,
|
||||
parent = obj->getParent();
|
||||
for (scopeIndex = 0;
|
||||
parent
|
||||
? js_IsCacheableNonGlobalScope(obj)
|
||||
? IsCacheableNonGlobalScope(obj)
|
||||
: !obj->getOps()->lookupProperty;
|
||||
++scopeIndex) {
|
||||
protoIndex =
|
||||
@ -5162,11 +5162,11 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
|
||||
* farther checks or lookups. For details see the JSOP_BINDNAME case of
|
||||
* js_Interpret.
|
||||
*
|
||||
* The test order here matters because js_IsCacheableNonGlobalScope
|
||||
* The test order here matters because IsCacheableNonGlobalScope
|
||||
* must not be passed a global object (i.e. one with null parent).
|
||||
*/
|
||||
for (int scopeIndex = 0;
|
||||
!obj->getParent() || js_IsCacheableNonGlobalScope(obj);
|
||||
!obj->getParent() || IsCacheableNonGlobalScope(obj);
|
||||
scopeIndex++) {
|
||||
JSObject *pobj;
|
||||
JSProperty *prop;
|
||||
|
@ -1661,16 +1661,19 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
|
||||
JSObject **objp, JSProperty **propp);
|
||||
|
||||
|
||||
extern JS_FRIEND_DATA(js::Class) js_CallClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* We cache name lookup results only for the global object or for native
|
||||
* non-global objects without prototype or with prototype that never mutates,
|
||||
* see bug 462734 and bug 487039.
|
||||
*/
|
||||
inline bool
|
||||
js_IsCacheableNonGlobalScope(JSObject *obj)
|
||||
static inline bool
|
||||
IsCacheableNonGlobalScope(JSObject *obj)
|
||||
{
|
||||
extern JS_FRIEND_DATA(js::Class) js_CallClass;
|
||||
extern JS_FRIEND_DATA(js::Class) js_DeclEnvClass;
|
||||
JS_ASSERT(obj->getParent());
|
||||
|
||||
js::Class *clasp = obj->getClass();
|
||||
@ -1682,6 +1685,8 @@ js_IsCacheableNonGlobalScope(JSObject *obj)
|
||||
return cacheable;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* If cacheResult is false, return JS_NO_PROP_CACHE_FILL on success.
|
||||
*/
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "jsobj.h"
|
||||
#include "jsprobes.h"
|
||||
#include "jspropertytree.h"
|
||||
#include "jsproxy.h"
|
||||
#include "jsscope.h"
|
||||
#include "jsstaticcheck.h"
|
||||
#include "jsxml.h"
|
||||
@ -60,6 +61,7 @@
|
||||
#include "jsscopeinlines.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "jsfuninlines.h"
|
||||
#include "jsgcinlines.h"
|
||||
#include "jsprobes.h"
|
||||
|
||||
|
@ -493,8 +493,10 @@ PropertyCache::purge(JSContext *cx)
|
||||
}
|
||||
|
||||
void
|
||||
PropertyCache::purgeForScript(JSScript *script)
|
||||
PropertyCache::purgeForScript(JSContext *cx, JSScript *script)
|
||||
{
|
||||
JS_ASSERT(!cx->runtime->gcRunning);
|
||||
|
||||
for (PropertyCacheEntry *entry = table; entry < table + SIZE; entry++) {
|
||||
if (JS_UPTRDIFF(entry->kpc, script->code) < script->length) {
|
||||
entry->kpc = NULL;
|
||||
|
@ -269,7 +269,7 @@ class PropertyCache
|
||||
const js::Shape *shape, JSBool adding = false);
|
||||
|
||||
void purge(JSContext *cx);
|
||||
void purgeForScript(JSScript *script);
|
||||
void purgeForScript(JSContext *cx, JSScript *script);
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
@ -623,8 +623,8 @@ js::PropertyTree::sweepShapes(JSContext *cx)
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
|
||||
bool
|
||||
js::PropertyTree::checkShapesAllUnmarked(JSContext *cx)
|
||||
void
|
||||
js::PropertyTree::unmarkShapes(JSContext *cx)
|
||||
{
|
||||
JSArena **ap = &arenaPool.first.next;
|
||||
while (JSArena *a = *ap) {
|
||||
@ -635,13 +635,10 @@ js::PropertyTree::checkShapesAllUnmarked(JSContext *cx)
|
||||
if (JSID_IS_VOID(shape->id))
|
||||
continue;
|
||||
|
||||
if (shape->marked())
|
||||
return false;
|
||||
shape->clearMark();
|
||||
}
|
||||
ap = &a->next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -128,7 +128,7 @@ class PropertyTree
|
||||
|
||||
void orphanChildren(js::Shape *shape);
|
||||
void sweepShapes(JSContext *cx);
|
||||
bool checkShapesAllUnmarked(JSContext *cx);
|
||||
void unmarkShapes(JSContext *cx);
|
||||
|
||||
static void dumpShapes(JSContext *cx);
|
||||
#ifdef DEBUG
|
||||
|
@ -1483,11 +1483,6 @@ PrintPropertyMethod(JSTracer *trc, char *buf, size_t bufsize)
|
||||
void
|
||||
Shape::trace(JSTracer *trc) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
JSRuntime *rt = trc->context->runtime;
|
||||
JS_ASSERT_IF(rt->gcCurrentCompartment, compartment == rt->gcCurrentCompartment);
|
||||
#endif
|
||||
|
||||
if (IS_GC_MARKING_TRACER(trc))
|
||||
mark();
|
||||
|
||||
|
@ -1617,15 +1617,11 @@ DestroyScript(JSContext *cx, JSScript *script)
|
||||
|
||||
/* FIXME: bug 506341; would like to do this only if regenerating shapes. */
|
||||
if (!cx->runtime->gcRunning) {
|
||||
JSStackFrame *fp = js_GetTopStackFrame(cx);
|
||||
|
||||
if (!(fp && fp->isEvalFrame())) {
|
||||
JS_PROPERTY_CACHE(cx).purgeForScript(script);
|
||||
JS_PROPERTY_CACHE(cx).purgeForScript(cx, script);
|
||||
|
||||
#ifdef CHECK_SCRIPT_OWNER
|
||||
JS_ASSERT(script->owner == cx->thread);
|
||||
JS_ASSERT(script->owner == cx->thread);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JS_TRACER
|
||||
|
@ -6595,7 +6595,7 @@ ScopeChainCheck(JSContext* cx, TreeFragment* f)
|
||||
*/
|
||||
JSObject* child = &cx->fp()->scopeChain();
|
||||
while (JSObject* parent = child->getParent()) {
|
||||
if (!js_IsCacheableNonGlobalScope(child)) {
|
||||
if (!IsCacheableNonGlobalScope(child)) {
|
||||
debug_only_print0(LC_TMTracer,"Blacklist: non-cacheable object on scope chain.\n");
|
||||
Blacklist((jsbytecode*) f->root->ip);
|
||||
return false;
|
||||
@ -7102,7 +7102,12 @@ RecordLoopEdge(JSContext* cx, TraceMonitor* tm, uintN& inlineCallCount)
|
||||
tm->recorder->assertInsideLoop();
|
||||
jsbytecode* pc = cx->regs->pc;
|
||||
if (pc == tm->recorder->tree->ip) {
|
||||
tm->recorder->closeLoop();
|
||||
AbortableRecordingStatus status = tm->recorder->closeLoop();
|
||||
if (status != ARECORD_COMPLETED) {
|
||||
if (tm->recorder)
|
||||
AbortRecording(cx, "closeLoop failed");
|
||||
return MONITOR_NOT_RECORDING;
|
||||
}
|
||||
} else {
|
||||
MonitorResult r = TraceRecorder::recordLoopEdge(cx, tm->recorder, inlineCallCount);
|
||||
JS_ASSERT((r == MONITOR_RECORDING) == (tm->recorder != NULL));
|
||||
@ -15182,7 +15187,7 @@ TraceRecorder::traverseScopeChain(JSObject *obj, LIns *obj_ins, JSObject *target
|
||||
/* There was a call object, or should be a call object now. */
|
||||
for (;;) {
|
||||
if (obj != globalObj) {
|
||||
if (!js_IsCacheableNonGlobalScope(obj))
|
||||
if (!IsCacheableNonGlobalScope(obj))
|
||||
RETURN_STOP("scope chain lookup crosses non-cacheable object");
|
||||
|
||||
// We must guard on the shape of all call objects for heavyweight functions
|
||||
|
@ -1187,7 +1187,7 @@ class ScopeNameCompiler : public PICStubCompiler
|
||||
JS_ASSERT_IF(pic.kind == ic::PICInfo::XNAME, getprop.obj == tobj);
|
||||
|
||||
while (tobj && tobj != getprop.holder) {
|
||||
if (!js_IsCacheableNonGlobalScope(tobj))
|
||||
if (!IsCacheableNonGlobalScope(tobj))
|
||||
return disable("non-cacheable scope chain object");
|
||||
JS_ASSERT(tobj->isNative());
|
||||
|
||||
@ -1539,7 +1539,7 @@ class BindNameCompiler : public PICStubCompiler
|
||||
JSObject *tobj = scopeChain;
|
||||
Address parent(pic.objReg, offsetof(JSObject, parent));
|
||||
while (tobj && tobj != obj) {
|
||||
if (!js_IsCacheableNonGlobalScope(tobj))
|
||||
if (!IsCacheableNonGlobalScope(tobj))
|
||||
return disable("non-cacheable obj in scope chain");
|
||||
masm.loadPtr(parent, pic.objReg);
|
||||
Jump nullTest = masm.branchTestPtr(Assembler::Zero, pic.objReg, pic.objReg);
|
||||
|
@ -333,86 +333,56 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false)
|
||||
JS_PROPERTY_CACHE(cx).test(cx, f.regs.pc, obj, obj2, entry, atom);
|
||||
if (!atom) {
|
||||
if (entry->vword.isFunObj()) {
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setObject(entry->vword.toFunObj());
|
||||
rval.setObject(entry->vword.toFunObj());
|
||||
} else if (entry->vword.isSlot()) {
|
||||
uintN slot = entry->vword.toSlot();
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1] = obj2->nativeGetSlot(slot);
|
||||
rval = obj2->nativeGetSlot(slot);
|
||||
} else {
|
||||
JS_ASSERT(entry->vword.isShape());
|
||||
shape = entry->vword.toShape();
|
||||
NATIVE_GET(cx, obj, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1] = rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* Push results, the same as below, but with a prop$ hit there
|
||||
* is no need to test for the unusual and uncacheable case where
|
||||
* the caller determines |this|.
|
||||
*/
|
||||
#if DEBUG
|
||||
Class *clasp;
|
||||
JS_ASSERT(!obj->getParent() ||
|
||||
(clasp = obj->getClass()) == &js_CallClass ||
|
||||
clasp == &js_BlockClass ||
|
||||
clasp == &js_DeclEnvClass);
|
||||
#endif
|
||||
if (callname) {
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setUndefined();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
jsid id;
|
||||
id = ATOM_TO_JSID(atom);
|
||||
JSProperty *prop;
|
||||
if (!js_FindPropertyHelper(cx, id, true, &obj, &obj2, &prop))
|
||||
return NULL;
|
||||
if (!prop) {
|
||||
/* Kludge to allow (typeof foo == "undefined") tests. */
|
||||
JSOp op2 = js_GetOpcode(cx, f.fp()->script(), f.regs.pc + JSOP_NAME_LENGTH);
|
||||
if (op2 == JSOP_TYPEOF) {
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setUndefined();
|
||||
return obj;
|
||||
}
|
||||
ReportAtomNotDefined(cx, atom);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Take the slow path if prop was not found in a native object. */
|
||||
if (!obj->isNative() || !obj2->isNative()) {
|
||||
if (!obj->getProperty(cx, id, &rval))
|
||||
return NULL;
|
||||
JS_ASSERT(obj->isGlobal() || IsCacheableNonGlobalScope(obj));
|
||||
} else {
|
||||
shape = (Shape *)prop;
|
||||
JSObject *normalized = obj;
|
||||
if (normalized->getClass() == &js_WithClass && !shape->hasDefaultGetter())
|
||||
normalized = js_UnwrapWithObject(cx, normalized);
|
||||
NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
|
||||
jsid id;
|
||||
id = ATOM_TO_JSID(atom);
|
||||
JSProperty *prop;
|
||||
if (!js_FindPropertyHelper(cx, id, true, &obj, &obj2, &prop))
|
||||
return NULL;
|
||||
if (!prop) {
|
||||
/* Kludge to allow (typeof foo == "undefined") tests. */
|
||||
JSOp op2 = js_GetOpcode(cx, f.fp()->script(), f.regs.pc + JSOP_NAME_LENGTH);
|
||||
if (op2 == JSOP_TYPEOF) {
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setUndefined();
|
||||
return obj;
|
||||
}
|
||||
ReportAtomNotDefined(cx, atom);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Take the slow path if prop was not found in a native object. */
|
||||
if (!obj->isNative() || !obj2->isNative()) {
|
||||
if (!obj->getProperty(cx, id, &rval))
|
||||
return NULL;
|
||||
} else {
|
||||
shape = (Shape *)prop;
|
||||
JSObject *normalized = obj;
|
||||
if (normalized->getClass() == &js_WithClass && !shape->hasDefaultGetter())
|
||||
normalized = js_UnwrapWithObject(cx, normalized);
|
||||
NATIVE_GET(cx, normalized, obj2, shape, JSGET_METHOD_BARRIER, &rval, return NULL);
|
||||
}
|
||||
}
|
||||
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1] = rval;
|
||||
*f.regs.sp++ = rval;
|
||||
|
||||
if (callname) {
|
||||
Class *clasp;
|
||||
JSObject *thisp = obj;
|
||||
if (!thisp->getParent() ||
|
||||
(clasp = thisp->getClass()) == &js_CallClass ||
|
||||
clasp == &js_BlockClass ||
|
||||
clasp == &js_DeclEnvClass) {
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setUndefined();
|
||||
} else {
|
||||
thisp = thisp->thisObject(cx);
|
||||
if (!thisp)
|
||||
return NULL;
|
||||
f.regs.sp++;
|
||||
f.regs.sp[-1].setObject(*thisp);
|
||||
}
|
||||
Value thisv;
|
||||
|
||||
if (!ComputeImplicitThis(cx, obj, rval, &thisv))
|
||||
return NULL;
|
||||
*f.regs.sp++ = thisv;
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
@ -3639,7 +3639,6 @@ resolver_resolve(JSContext *cx, JSObject *obj, jsid id, uintN flags, JSObject **
|
||||
JS_ALWAYS_TRUE(JS_GetReservedSlot(cx, obj, 0, &v));
|
||||
return CopyProperty(cx, obj, JSVAL_TO_OBJECT(v), id, flags, objp);
|
||||
}
|
||||
static JSNewResolveOp resolver_resolve_check = resolver_resolve;
|
||||
|
||||
static JSBool
|
||||
resolver_enumerate(JSContext *cx, JSObject *obj)
|
||||
@ -4477,6 +4476,40 @@ StringStats(JSContext *cx, uintN argc, jsval *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
enum CompartmentKind { SAME_COMPARTMENT, NEW_COMPARTMENT };
|
||||
|
||||
static JSObject *
|
||||
NewGlobalObject(JSContext *cx, CompartmentKind compartment);
|
||||
|
||||
JSBool
|
||||
NewGlobal(JSContext *cx, uintN argc, jsval *vp)
|
||||
{
|
||||
if (argc != 1 || !JSVAL_IS_STRING(JS_ARGV(cx, vp)[0])) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "newGlobal");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString *str = JSVAL_TO_STRING(JS_ARGV(cx, vp)[0]);
|
||||
|
||||
JSBool equalSame = JS_FALSE, equalNew = JS_FALSE;
|
||||
if (!JS_StringEqualsAscii(cx, str, "same-compartment", &equalSame) ||
|
||||
!JS_StringEqualsAscii(cx, str, "new-compartment", &equalNew)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!equalSame && !equalNew) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "newGlobal");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject *global = NewGlobalObject(cx, equalSame ? SAME_COMPARTMENT : NEW_COMPARTMENT);
|
||||
if (!global)
|
||||
return false;
|
||||
|
||||
JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(global));
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSFunctionSpec shell_functions[] = {
|
||||
JS_FN("version", Version, 0,0),
|
||||
JS_FN("revertVersion", RevertVersion, 0,0),
|
||||
@ -4574,6 +4607,7 @@ static JSFunctionSpec shell_functions[] = {
|
||||
JS_FN("mjitstats", MJitStats, 0,0),
|
||||
#endif
|
||||
JS_FN("stringstats", StringStats, 0,0),
|
||||
JS_FN("newGlobal", NewGlobal, 1,0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
||||
@ -4599,7 +4633,7 @@ static const char *const shell_help_messages[] = {
|
||||
"assertEq(actual, expected[, msg])\n"
|
||||
" Throw if the first two arguments are not the same (both +0 or both -0,\n"
|
||||
" both NaN, or non-zero and ===)",
|
||||
"assertJit() Throw if the calling function failed to JIT\n",
|
||||
"assertJit() Throw if the calling function failed to JIT",
|
||||
"gc() Run the garbage collector",
|
||||
#ifdef JS_GCMETER
|
||||
"gcstats() Print garbage collector statistics",
|
||||
@ -4644,7 +4678,7 @@ static const char *const shell_help_messages[] = {
|
||||
"dumpObject() Dump an internal representation of an object",
|
||||
"notes([fun]) Show source notes for functions",
|
||||
"tracing([true|false|filename]) Turn bytecode execution tracing on/off.\n"
|
||||
" With filename, send to file.\n",
|
||||
" With filename, send to file.",
|
||||
"stats([string ...]) Dump 'arena', 'atom', 'global' stats",
|
||||
#endif
|
||||
#ifdef TEST_CVTARGS
|
||||
@ -4697,24 +4731,37 @@ static const char *const shell_help_messages[] = {
|
||||
" Get/Set the limit in seconds for the execution time for the current context.\n"
|
||||
" A negative value (default) means that the execution time is unlimited.",
|
||||
"elapsed() Execution time elapsed for the current context.",
|
||||
"parent(obj) Returns the parent of obj.\n",
|
||||
"wrap(obj) Wrap an object into a noop wrapper.\n",
|
||||
"serialize(sd) Serialize sd using JS_WriteStructuredClone. Returns a TypedArray.\n",
|
||||
"deserialize(a) Deserialize data generated by serialize.\n",
|
||||
"parent(obj) Returns the parent of obj.",
|
||||
"wrap(obj) Wrap an object into a noop wrapper.",
|
||||
"serialize(sd) Serialize sd using JS_WriteStructuredClone. Returns a TypedArray.",
|
||||
"deserialize(a) Deserialize data generated by serialize.",
|
||||
#ifdef JS_METHODJIT
|
||||
"mjitstats() Return stats on mjit memory usage.\n",
|
||||
"mjitstats() Return stats on mjit memory usage.",
|
||||
#endif
|
||||
"stringstats() Return stats on string memory usage.\n"
|
||||
"stringstats() Return stats on string memory usage.",
|
||||
"newGlobal(kind) Return a new global object, in the current\n"
|
||||
" compartment if kind === 'same-compartment' or in a\n"
|
||||
" new compartment if kind === 'new-compartment'",
|
||||
|
||||
/* Keep these last: see the static assertion below. */
|
||||
#ifdef MOZ_PROFILING
|
||||
"startProfiling() Start a profiling session.\n"
|
||||
" Profiler must be running with programatic sampling\n"
|
||||
"stopProfiling() Stop a running profiling session"
|
||||
" Profiler must be running with programatic sampling",
|
||||
"stopProfiling() Stop a running profiling session\n"
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef MOZ_PROFILING
|
||||
#define PROFILING_FUNCTION_COUNT 2
|
||||
#else
|
||||
#define PROFILING_FUNCTION_COUNT 0
|
||||
#endif
|
||||
|
||||
/* Help messages must match shell functions. */
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) + 1 ==
|
||||
JS_ARRAY_LENGTH(shell_functions));
|
||||
JS_STATIC_ASSERT(JS_ARRAY_LENGTH(shell_help_messages) - PROFILING_FUNCTION_COUNT ==
|
||||
JS_ARRAY_LENGTH(shell_functions) - 1 /* JS_FS_END */);
|
||||
|
||||
#undef PROFILING_FUNCTION_COUNT
|
||||
|
||||
#ifdef DEBUG
|
||||
static void
|
||||
@ -4723,12 +4770,13 @@ CheckHelpMessages()
|
||||
const char *const *m;
|
||||
const char *lp;
|
||||
|
||||
/* Each message must begin with "function_name(" prefix. */
|
||||
/* Messages begin with "function_name(" prefix and don't end with \n. */
|
||||
for (m = shell_help_messages; m != JS_ARRAY_END(shell_help_messages); ++m) {
|
||||
lp = strchr(*m, '(');
|
||||
JS_ASSERT(lp);
|
||||
JS_ASSERT(memcmp(shell_functions[m - shell_help_messages].name,
|
||||
*m, lp - *m) == 0);
|
||||
JS_ASSERT((*m)[strlen(*m) - 1] != '\n');
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -5548,46 +5596,52 @@ DestroyContext(JSContext *cx, bool withGC)
|
||||
}
|
||||
|
||||
static JSObject *
|
||||
NewGlobalObject(JSContext *cx)
|
||||
NewGlobalObject(JSContext *cx, CompartmentKind compartment)
|
||||
{
|
||||
JSObject *glob = JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL);
|
||||
JSObject *glob = (compartment == NEW_COMPARTMENT)
|
||||
? JS_NewCompartmentAndGlobalObject(cx, &global_class, NULL)
|
||||
: JS_NewGlobalObject(cx, &global_class);
|
||||
if (!glob)
|
||||
return NULL;
|
||||
|
||||
JSAutoEnterCompartment ac;
|
||||
if (!ac.enter(cx, glob))
|
||||
return NULL;
|
||||
{
|
||||
JSAutoEnterCompartment ac;
|
||||
if (!ac.enter(cx, glob))
|
||||
return NULL;
|
||||
|
||||
#ifdef LAZY_STANDARD_CLASSES
|
||||
JS_SetGlobalObject(cx, glob);
|
||||
#else
|
||||
if (!JS_InitStandardClasses(cx, glob))
|
||||
return NULL;
|
||||
#ifndef LAZY_STANDARD_CLASSES
|
||||
if (!JS_InitStandardClasses(cx, glob))
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
#ifdef JS_HAS_CTYPES
|
||||
if (!JS_InitCTypesClass(cx, glob))
|
||||
return NULL;
|
||||
if (!JS_InitCTypesClass(cx, glob))
|
||||
return NULL;
|
||||
#endif
|
||||
if (!JS::RegisterPerfMeasurement(cx, glob))
|
||||
return NULL;
|
||||
if (!JS_DefineFunctions(cx, glob, shell_functions) ||
|
||||
!JS_DefineProfilingFunctions(cx, glob)) {
|
||||
return NULL;
|
||||
if (!JS::RegisterPerfMeasurement(cx, glob))
|
||||
return NULL;
|
||||
if (!JS_DefineFunctions(cx, glob, shell_functions) ||
|
||||
!JS_DefineProfilingFunctions(cx, glob)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSObject *it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0);
|
||||
if (!it)
|
||||
return NULL;
|
||||
if (!JS_DefineProperties(cx, it, its_props))
|
||||
return NULL;
|
||||
if (!JS_DefineFunctions(cx, it, its_methods))
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineProperty(cx, glob, "custom", JSVAL_VOID, its_getter,
|
||||
its_setter, 0))
|
||||
return NULL;
|
||||
if (!JS_DefineProperty(cx, glob, "customRdOnly", JSVAL_VOID, its_getter,
|
||||
its_setter, JSPROP_READONLY))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
JSObject *it = JS_DefineObject(cx, glob, "it", &its_class, NULL, 0);
|
||||
if (!it)
|
||||
return NULL;
|
||||
if (!JS_DefineProperties(cx, it, its_props))
|
||||
return NULL;
|
||||
if (!JS_DefineFunctions(cx, it, its_methods))
|
||||
return NULL;
|
||||
|
||||
if (!JS_DefineProperty(cx, glob, "custom", JSVAL_VOID, its_getter,
|
||||
its_setter, 0))
|
||||
return NULL;
|
||||
if (!JS_DefineProperty(cx, glob, "customRdOnly", JSVAL_VOID, its_getter,
|
||||
its_setter, JSPROP_READONLY))
|
||||
if (compartment == NEW_COMPARTMENT && !JS_WrapObject(cx, &glob))
|
||||
return NULL;
|
||||
|
||||
return glob;
|
||||
@ -5598,7 +5652,7 @@ Shell(JSContext *cx, int argc, char **argv, char **envp)
|
||||
{
|
||||
JSAutoRequest ar(cx);
|
||||
|
||||
JSObject *glob = NewGlobalObject(cx);
|
||||
JSObject *glob = NewGlobalObject(cx, NEW_COMPARTMENT);
|
||||
if (!glob)
|
||||
return 1;
|
||||
|
||||
@ -5606,6 +5660,8 @@ Shell(JSContext *cx, int argc, char **argv, char **envp)
|
||||
if (!ac.enter(cx, glob))
|
||||
return 1;
|
||||
|
||||
JS_SetGlobalObject(cx, glob);
|
||||
|
||||
JSObject *envobj = JS_DefineObject(cx, glob, "environment", &env_class, NULL, 0);
|
||||
if (!envobj || !JS_SetPrivate(cx, envobj, envp))
|
||||
return 1;
|
||||
@ -5642,7 +5698,7 @@ Shell(JSContext *cx, int argc, char **argv, char **envp)
|
||||
class ShellWorkerHooks : public js::workers::WorkerHooks {
|
||||
public:
|
||||
JSObject *newGlobalObject(JSContext *cx) {
|
||||
return NewGlobalObject(cx);
|
||||
return NewGlobalObject(cx, NEW_COMPARTMENT);
|
||||
}
|
||||
};
|
||||
ShellWorkerHooks hooks;
|
||||
|
@ -15,6 +15,6 @@ script regress-352789.js
|
||||
script regress-355101.js
|
||||
script regress-355474-01.js
|
||||
skip script regress-373678.js # obsolete test
|
||||
script regress-429249.js
|
||||
skip script regress-429249.js
|
||||
script regress-461233.js
|
||||
script regress-463360.js
|
||||
|
@ -32,4 +32,4 @@ script 15.8-1.js
|
||||
script 15.9.5.js
|
||||
script 8.6.2.1-1.js
|
||||
script 9.9-1.js
|
||||
script trapflatclosure.js
|
||||
skip script trapflatclosure.js
|
||||
|
@ -11,5 +11,5 @@ script regress-320854.js
|
||||
script regress-327170.js
|
||||
script regress-368516.js
|
||||
script regress-385393-03.js
|
||||
script regress-429248.js
|
||||
skip script regress-429248.js
|
||||
script regress-430740.js
|
||||
|
@ -164,16 +164,16 @@ skip script regress-418730.js # obsolete test
|
||||
script regress-420612.js
|
||||
script regress-420869-01.js
|
||||
skip script regress-421621.js # obsolete test
|
||||
script regress-422137.js
|
||||
skip script regress-422137.js
|
||||
script regress-422592.js
|
||||
script regress-424683-01.js
|
||||
script regress-426711.js
|
||||
script regress-427196-01.js
|
||||
script regress-427196-02.js
|
||||
script regress-427196-03.js
|
||||
script regress-429264.js
|
||||
skip script regress-429264.js
|
||||
script regress-429739.js
|
||||
script regress-431428.js
|
||||
skip script regress-431428.js
|
||||
skip script regress-432075.js # obsolete test
|
||||
script regress-434837-01.js
|
||||
fails script regress-435345-01.js
|
||||
|
@ -46,4 +46,4 @@ script regress-379925.js
|
||||
script regress-380506.js
|
||||
script regress-410571.js
|
||||
script regress-410649.js
|
||||
script regress-429252.js
|
||||
skip script regress-429252.js
|
||||
|
@ -89,3 +89,5 @@ script regress-634210-1.js
|
||||
script regress-634210-2.js
|
||||
script regress-634210-3.js
|
||||
script regress-634210-4.js
|
||||
script regress-635195.js
|
||||
script regress-636364.js
|
||||
|
@ -8,7 +8,11 @@ if (typeof evalcx == 'function') {
|
||||
var cx = evalcx("");
|
||||
evalcx("function f() { return this; }", cx);
|
||||
f = cx.f;
|
||||
assertEq(f(), cx);
|
||||
assertEq(f(), this);
|
||||
|
||||
evalcx("function g() { 'use strict'; return this; }", cx);
|
||||
g = cx.g;
|
||||
assertEq(g(), undefined);
|
||||
}
|
||||
|
||||
reportCompare(0, 0, "");
|
||||
reportCompare(0, 0, "ok");
|
||||
|
8
js/src/tests/js1_8_5/regress/regress-635195.js
Normal file
8
js/src/tests/js1_8_5/regress/regress-635195.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
var obj = {set x(v) {}};
|
||||
obj.watch("x", function() { delete obj.x; });
|
||||
obj.x = "hi"; // don't assert
|
||||
|
||||
reportCompare(0, 0, 'ok');
|
29
js/src/tests/js1_8_5/regress/regress-636364.js
Normal file
29
js/src/tests/js1_8_5/regress/regress-636364.js
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/licenses/publicdomain/
|
||||
* Contributors: Jason Orendorff, Brendan Eich
|
||||
*/
|
||||
|
||||
if (typeof newGlobal == 'function') {
|
||||
var gsame = newGlobal('same-compartment');
|
||||
|
||||
gsame.eval("function f() { return this; }");
|
||||
f = gsame.f;
|
||||
assertEq(f(), this);
|
||||
|
||||
gsame.eval("function g() { 'use strict'; return this; }");
|
||||
g = gsame.g;
|
||||
assertEq(g(), undefined);
|
||||
|
||||
var gnew = newGlobal('new-compartment');
|
||||
|
||||
gnew.eval("function f() { return this; }");
|
||||
f = gnew.f;
|
||||
assertEq(f(), this);
|
||||
|
||||
gnew.eval("function g() { 'use strict'; return this; }");
|
||||
g = gnew.g;
|
||||
assertEq(g(), undefined);
|
||||
}
|
||||
|
||||
reportCompare(0, 0, "ok");
|
Loading…
Reference in New Issue
Block a user