static JSBool FindConstructor(JSContext *cx, JSClass *clasp, jsval *vp) { JSAtom *atom; JSObject *obj, *tmp; JSBool ok; PR_ASSERT(JS_IS_LOCKED(cx)); /* XXX pre-atomize in JS_InitClass! */ atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0); if (!atom) return JS_FALSE; if (cx->fp && (tmp = cx->fp->scopeChain)) { /* Find the topmost object in the scope chain. */ do { obj = tmp; tmp = OBJ_GET_PARENT(obj); } while (tmp); } else { obj = cx->globalObject; if (!obj) { *vp = JSVAL_VOID; return JS_TRUE; } } ok = (js_GetProperty(cx, obj, (jsval)atom, vp) != NULL); js_DropAtom(cx, atom); return JS_TRUE; }
JSObject * js_FindVariableScope(JSContext *cx, JSFunction **funp) { JSStackFrame *fp; JSObject *obj, *parent, *withobj; JSClass *clasp; JSFunction *fun; PR_ASSERT(JS_IS_LOCKED(cx)); fp = cx->fp; for (obj = fp->scopeChain, withobj = NULL; ; obj = parent) { parent = OBJ_GET_PARENT(obj); clasp = obj->map->clasp; if (!parent || clasp != &js_WithClass) break; withobj = obj; } fun = (clasp == &js_FunctionClass) ? JS_GetPrivate(cx, obj) : NULL; #if JS_HAS_CALL_OBJECT if (fun && fun->script) { for (; fp && fp->fun != fun; fp = fp->down) ; if (fp) { obj = js_GetCallObject(cx, fp, parent); if (withobj) OBJ_SET_PARENT(withobj, obj); } } #endif *funp = fun; return obj; }
static JSBool IteratorNextImpl(JSContext *cx, JSObject *obj, jsval *rval) { JSObject *iterable; jsval state; uintN flags; JSBool foreach, ok; jsid id; JS_ASSERT(OBJ_GET_CLASS(cx, obj) == &js_IteratorClass); iterable = OBJ_GET_PARENT(cx, obj); JS_ASSERT(iterable); state = STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE); if (JSVAL_IS_NULL(state)) goto stop; flags = JSVAL_TO_INT(STOBJ_GET_SLOT(obj, JSSLOT_ITER_FLAGS)); JS_ASSERT(!(flags & JSITER_ENUMERATE)); foreach = (flags & JSITER_FOREACH) != 0; ok = #if JS_HAS_XML_SUPPORT (foreach && OBJECT_IS_XML(cx, iterable)) ? ((JSXMLObjectOps *) iterable->map->ops)-> enumerateValues(cx, iterable, JSENUMERATE_NEXT, &state, &id, rval) : #endif OBJ_ENUMERATE(cx, iterable, JSENUMERATE_NEXT, &state, &id); if (!ok) return JS_FALSE; STOBJ_SET_SLOT(obj, JSSLOT_ITER_STATE, state); if (JSVAL_IS_NULL(state)) goto stop; if (foreach) { #if JS_HAS_XML_SUPPORT if (!OBJECT_IS_XML(cx, iterable) && !OBJ_GET_PROPERTY(cx, iterable, id, rval)) { return JS_FALSE; } #endif if (!NewKeyValuePair(cx, id, *rval, rval)) return JS_FALSE; } else { *rval = ID_TO_VALUE(id); } return JS_TRUE; stop: JS_ASSERT(STOBJ_GET_SLOT(obj, JSSLOT_ITER_STATE) == JSVAL_NULL); *rval = JSVAL_HOLE; return JS_TRUE; }
static int sort_compare(const void *a, const void *b, void *arg) { jsval av = *(const jsval *)a, bv = *(const jsval *)b; CompareArgs *ca = (CompareArgs *) arg; JSContext *cx = ca->context; jsdouble cmp = -1; jsval fval, argv[2], rval; JSBool ok; fval = ca->fval; if (fval == JSVAL_NULL) { JSString *astr, *bstr; if (av == bv) { cmp = 0; } else if (av == JSVAL_VOID || bv == JSVAL_VOID) { /* Put undefined properties at the end. */ cmp = (av == JSVAL_VOID) ? 1 : -1; } else if ((astr = js_ValueToString(cx, av)) != NULL && (bstr = js_ValueToString(cx, bv)) != NULL) { cmp = js_CompareStrings(astr, bstr); } else { ca->status = JS_FALSE; } } else { argv[0] = av; argv[1] = bv; ok = js_InternalCall(cx, OBJ_GET_PARENT(cx, JSVAL_TO_OBJECT(fval)), fval, 2, argv, &rval); if (ok) { ok = js_ValueToNumber(cx, rval, &cmp); /* Clamp cmp to -1, 0, 1. */ if (JSDOUBLE_IS_NaN(cmp)) { /* XXX report some kind of error here? ECMA talks about * 'consistent compare functions' that don't return NaN, but is * silent about what the result should be. So we currently * ignore it. */ cmp = 0; } else if (cmp != 0) { cmp = cmp > 0 ? 1 : -1; } } else { ca->status = ok; } } return (int)cmp; }
JSBool js_FindProperty(JSContext *cx, jsval id, JSObject **objp, JSProperty **propp) { JSRuntime *rt; JSObject *obj, *parent, *lastobj; JSProperty *prop; rt = cx->runtime; PR_ASSERT(JS_IS_RUNTIME_LOCKED(rt)); for (obj = cx->fp->scopeChain; obj; obj = parent) { /* Try the property cache and return immediately on cache hit. */ PROPERTY_CACHE_TEST(&rt->propertyCache, obj, id, prop); if (PROP_FOUND(prop)) { *objp = obj; *propp = prop; return JS_TRUE; } /* * Set parent here, after cache hit to minimize cycles in that case, * but before js_LookupProperty, which might change obj. */ parent = OBJ_GET_PARENT(obj); /* If cache miss (not cached-as-not-found), take the slow path. */ if (!prop) { if (!js_LookupProperty(cx, obj, id, &obj, &prop)) return JS_FALSE; if (prop) { PROPERTY_CACHE_FILL(cx, &rt->propertyCache, obj, id, prop); *objp = obj; *propp = prop; return JS_TRUE; } /* No such property -- cache obj[id] as not-found. */ PROPERTY_CACHE_FILL(cx, &rt->propertyCache, obj, id, PROP_NOT_FOUND); } lastobj = obj; } *objp = lastobj; *propp = NULL; return JS_TRUE; }
JSPropertyOp js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter) { JSAtom *atom; JSFunction *wrapper; if (!(attrs & JSPROP_SETTER)) return &js_watch_set; /* & to silence schoolmarmish MSVC */ if (!JSVAL_IS_INT(id)) { atom = (JSAtom *)id; } else { atom = js_AtomizeInt(cx, JSVAL_TO_INT(id), 0); if (!atom) return NULL; } wrapper = js_NewFunction(cx, NULL, js_watch_set_wrapper, 1, 0, OBJ_GET_PARENT(cx, (JSObject *)setter), atom); if (!wrapper) return NULL; return (JSPropertyOp) wrapper->object; }
static JSBool obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { JSStackFrame *fp, *caller; JSBool ok; JSString *str; const char *file; uintN line; JSPrincipals *principals; JSScript *script; #if JS_HAS_EVAL_THIS_SCOPE JSObject *callerScopeChain; JSBool implicitWith; #endif if (!JSVAL_IS_STRING(argv[0])) { *rval = argv[0]; return JS_TRUE; } fp = cx->fp; caller = fp->down; #if !JS_BUG_EVAL_THIS_FUN /* Ensure that this flows into eval from the calling function, if any. */ fp->thisp = caller->thisp; #endif #if JS_HAS_SHARP_VARS fp->sharpArray = caller->sharpArray; #endif #if JS_HAS_EVAL_THIS_SCOPE /* If obj.eval(str), emulate 'with (obj) eval(str)' in the calling frame. */ callerScopeChain = caller->scopeChain; implicitWith = (callerScopeChain != obj && (callerScopeChain->map->clasp != &js_WithClass || OBJ_GET_PROTO(callerScopeChain) != obj)); if (implicitWith) { obj = js_NewObject(cx, &js_WithClass, obj, callerScopeChain); if (!obj) return JS_FALSE; caller->scopeChain = obj; } #endif #if !JS_BUG_EVAL_THIS_SCOPE /* Compile using caller's current scope object (might be a function). */ obj = caller->scopeChain; #endif str = JSVAL_TO_STRING(argv[0]); if (caller->script) { file = caller->script->filename; line = js_PCToLineNumber(caller->script, caller->pc); principals = caller->script->principals; } else { file = NULL; line = 0; principals = NULL; } script = JS_CompileUCScriptForPrincipals(cx, obj, principals, str->chars, str->length, file, line); if (!script) { ok = JS_FALSE; goto out; } #if !JS_BUG_EVAL_THIS_SCOPE /* Interpret using caller's new scope object (might be a Call object). */ obj = caller->scopeChain; #endif ok = js_Execute(cx, obj, script, fp, rval); JS_DestroyScript(cx, script); out: #if JS_HAS_EVAL_THIS_SCOPE if (implicitWith) { /* Restore OBJ_GET_PARENT(obj) not callerScopeChain in case of Call. */ caller->scopeChain = OBJ_GET_PARENT(obj); } #endif return ok; }