📄 jsfun.c
字号:
return JS_FALSE; } } js_CallNewScriptHook(cx, fun->script, fun); } return JS_TRUE;}#else /* !JS_HAS_XDR */#define fun_xdrObject NULL#endif /* !JS_HAS_XDR */#if JS_HAS_INSTANCEOF/* * [[HasInstance]] internal method for Function objects: fetch the .prototype * property of its 'this' parameter, and walks the prototype chain of v (only * if v is an object) returning true if .prototype is found. */static JSBoolfun_hasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp){ jsval pval, cval; JSString *str; JSObject *proto, *obj2; JSFunction *cfun, *ofun; if (!OBJ_GET_PROPERTY(cx, obj, (jsid)cx->runtime->atomState.classPrototypeAtom, &pval)) { return JS_FALSE; } if (JSVAL_IS_PRIMITIVE(pval)) { /* * Throw a runtime error if instanceof is called on a function that * has a non-object as its .prototype value. */ str = js_DecompileValueGenerator(cx, -1, OBJECT_TO_JSVAL(obj), NULL); if (str) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_PROTOTYPE, JS_GetStringBytes(str)); } return JS_FALSE; } proto = JSVAL_TO_OBJECT(pval); if (!js_IsDelegate(cx, proto, v, bp)) return JS_FALSE; if (!*bp && !JSVAL_IS_PRIMITIVE(v) && v != pval) { /* * Extension for "brutal sharing" of standard class constructors: if * a script is compiled using a single, shared set of constructors, in * particular Function and RegExp, but executed many times using other * sets of standard constructors, then (/re/ instanceof RegExp), e.g., * will be false. * * We extend instanceof in this case to look for a matching native or * script underlying the function object found in the 'constructor' * property of the object in question (which is JSVAL_TO_OBJECT(v)), * or found in the 'constructor' property of one of its prototypes. * * See also jsexn.c, where the *Error constructors are defined, each * with its own native function, to satisfy (e instanceof Error) even * when exceptions cross standard-class sharing boundaries. Note that * Error.prototype may not lie on e's __proto__ chain in that case. */ obj2 = JSVAL_TO_OBJECT(v); do { if (!OBJ_GET_PROPERTY(cx, obj2, (jsid)cx->runtime->atomState.constructorAtom, &cval)) { return JS_FALSE; } if (JSVAL_IS_FUNCTION(cx, cval)) { cfun = (JSFunction *) JS_GetPrivate(cx, JSVAL_TO_OBJECT(cval)); ofun = (JSFunction *) JS_GetPrivate(cx, obj); if (cfun->native == ofun->native && cfun->script == ofun->script) { *bp = JS_TRUE; break; } } } while ((obj2 = OBJ_GET_PROTO(cx, obj2)) != NULL); } return JS_TRUE;}#else /* !JS_HAS_INSTANCEOF */#define fun_hasInstance NULL#endif /* !JS_HAS_INSTANCEOF */static uint32fun_mark(JSContext *cx, JSObject *obj, void *arg){ JSFunction *fun; fun = (JSFunction *) JS_GetPrivate(cx, obj); if (fun) { if (fun->atom) GC_MARK_ATOM(cx, fun->atom, arg); if (fun->script) js_MarkScript(cx, fun->script, arg); } return 0;}/* * Reserve two slots in all function objects for XPConnect. Note that this * does not bloat every instance, only those on which reserved slots are set, * and those on which ad-hoc properties are defined. */JSClass js_FunctionClass = { js_Function_str, JSCLASS_HAS_PRIVATE | JSCLASS_NEW_RESOLVE | JSCLASS_HAS_RESERVED_SLOTS(2), JS_PropertyStub, JS_PropertyStub, fun_getProperty, JS_PropertyStub, JS_EnumerateStub, (JSResolveOp)fun_resolve, fun_convert, fun_finalize, NULL, NULL, NULL, NULL, fun_xdrObject, fun_hasInstance, fun_mark, 0};JSBooljs_fun_toString(JSContext *cx, JSObject *obj, uint32 indent, uintN argc, jsval *argv, jsval *rval){ jsval fval; JSFunction *fun; JSString *str; if (!argv) { JS_ASSERT(JS_ObjectIsFunction(cx, obj)); } else { fval = argv[-1]; if (!JSVAL_IS_FUNCTION(cx, fval)) { /* * If we don't have a function to start off with, try converting * the object to a function. If that doesn't work, complain. */ if (JSVAL_IS_OBJECT(fval)) { obj = JSVAL_TO_OBJECT(fval); if (!OBJ_GET_CLASS(cx, obj)->convert(cx, obj, JSTYPE_FUNCTION, &fval)) { return JS_FALSE; } } if (!JSVAL_IS_FUNCTION(cx, fval)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, js_Function_str, js_toString_str, JS_GetTypeName(cx, JS_TypeOfValue(cx, fval))); return JS_FALSE; } } obj = JSVAL_TO_OBJECT(fval); } fun = (JSFunction *) JS_GetPrivate(cx, obj); if (!fun) return JS_TRUE; if (argc && !js_ValueToECMAUint32(cx, argv[0], &indent)) return JS_FALSE; str = JS_DecompileFunction(cx, fun, (uintN)indent); if (!str) return JS_FALSE; *rval = STRING_TO_JSVAL(str); return JS_TRUE;}static JSBoolfun_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSString *string = JS_InternString (cx, "[type Function]"); if (string == NULL) return JS_FALSE; *rval = STRING_TO_JSVAL (string); return JS_TRUE;}#if JS_HAS_TOSOURCEstatic JSBoolfun_toSource(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return js_fun_toString(cx, obj, JS_DONT_PRETTY_PRINT, argc, argv, rval);}#endifstatic const char js_call_str[] = "call";#if JS_HAS_CALL_FUNCTIONstatic JSBoolfun_call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ jsval fval, *sp, *oldsp; void *mark; uintN i; JSStackFrame *fp; JSBool ok; if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &argv[-1])) return JS_FALSE; fval = argv[-1]; if (!JSVAL_IS_FUNCTION(cx, fval)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, js_Function_str, js_call_str, JS_GetStringBytes(JS_ValueToString(cx, fval))); return JS_FALSE; } if (argc == 0) { /* Call fun with its parent as the 'this' parameter if no args. */ obj = OBJ_GET_PARENT(cx, obj); } else { /* Otherwise convert the first arg to 'this' and skip over it. */ if (!js_ValueToObject(cx, argv[0], &obj)) return JS_FALSE; argc--; argv++; } /* Allocate stack space for fval, obj, and the args. */ sp = js_AllocStack(cx, 2 + argc, &mark); if (!sp) return JS_FALSE; /* Push fval, obj, and the args. */ *sp++ = fval; *sp++ = OBJECT_TO_JSVAL(obj); for (i = 0; i < argc; i++) *sp++ = argv[i]; /* Lift current frame to include the args and do the call. */ fp = cx->fp; oldsp = fp->sp; fp->sp = sp; ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER); /* Store rval and pop stack back to our frame's sp. */ *rval = fp->sp[-1]; fp->sp = oldsp; js_FreeStack(cx, mark); return ok;}#endif /* JS_HAS_CALL_FUNCTION */#if JS_HAS_APPLY_FUNCTIONstatic JSBoolfun_apply(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ jsval fval, *sp, *oldsp; JSObject *aobj; jsuint length; void *mark; uintN i; JSBool ok; JSStackFrame *fp; if (argc == 0) { /* Will get globalObject as 'this' and no other arguments. */ return fun_call(cx, obj, argc, argv, rval); } if (!OBJ_DEFAULT_VALUE(cx, obj, JSTYPE_FUNCTION, &argv[-1])) return JS_FALSE; fval = argv[-1]; if (!JSVAL_IS_FUNCTION(cx, fval)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, js_Function_str, "apply", JS_GetStringBytes(JS_ValueToString(cx, fval))); return JS_FALSE; } /* Quell GCC overwarnings. */ aobj = NULL; length = 0; if (argc >= 2) { /* If the 2nd arg is null or void, call the function with 0 args. */ if (JSVAL_IS_NULL(argv[1]) || JSVAL_IS_VOID(argv[1])) { argc = 0; } else { /* The second arg must be an array (or arguments object). */ if (JSVAL_IS_PRIMITIVE(argv[1]) || (aobj = JSVAL_TO_OBJECT(argv[1]), OBJ_GET_CLASS(cx, aobj) != &js_ArgumentsClass && OBJ_GET_CLASS(cx, aobj) != &js_ArrayClass)) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_BAD_APPLY_ARGS); return JS_FALSE; } if (!js_GetLengthProperty(cx, aobj, &length)) return JS_FALSE; } } /* Convert the first arg to 'this' and skip over it. */ if (!js_ValueToObject(cx, argv[0], &obj)) return JS_FALSE; /* Allocate stack space for fval, obj, and the args. */ argc = (uintN)JS_MIN(length, ARGC_LIMIT - 1); sp = js_AllocStack(cx, 2 + argc, &mark); if (!sp) return JS_FALSE; /* Push fval, obj, and aobj's elements as args. */ *sp++ = fval; *sp++ = OBJECT_TO_JSVAL(obj); for (i = 0; i < argc; i++) { ok = JS_GetElement(cx, aobj, (jsint)i, sp); if (!ok) goto out; sp++; } /* Lift current frame to include the args and do the call. */ fp = cx->fp; oldsp = fp->sp; fp->sp = sp; ok = js_Invoke(cx, argc, JSINVOKE_INTERNAL | JSINVOKE_SKIP_CALLER); /* Store rval and pop stack back to our frame's sp. */ *rval = fp->sp[-1]; fp->sp = oldsp;out: js_FreeStack(cx, mark); return ok;}#endif /* JS_HAS_APPLY_FUNCTION */static JSFunctionSpec function_methods[] = {#if JS_HAS_TOSOURCE {js_toSource_str, fun_toSource, 0,0,0},#endif {js_toString_str, fun_toString, 1,0,0},#if JS_HAS_APPLY_FUNCTION {"apply", fun_apply, 2,0,0},#endif#if JS_HAS_CALL_FUNCTION {js_call_str, fun_call, 1,0,0},#endif {0,0,0,0,0}};JSBooljs_IsIdentifier(JSString *str){ size_t n; jschar *s, c; n = JSSTRING_LENGTH(str); if (n == 0) return JS_FALSE; s = JSSTRING_CHARS(str); c = *s; if (!JS_ISIDENT_START(c)) return JS_FALSE; for (n--; n != 0; n--) { c = *++s; if (!JS_ISIDENT(c)) return JS_FALSE; } return JS_TRUE;}static JSBoolFunction(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSStackFrame *fp, *caller; JSFunction *fun; JSObject *parent; uintN i, n, lineno, dupflag; JSAtom *atom; const char *filename; JSObject *obj2; JSScopeProperty *sprop; JSString *str, *arg; void *mark; JSTokenStream *ts; JSPrincipals *principals; jschar *collected_args, *cp; size_t arg_length, args_length; JSTokenType tt; JSBool ok; fp = cx->fp; if (fp && !(fp->flags & JSFRAME_CONSTRUCTING)) { obj = js_NewObject(cx, &js_FunctionClass, NULL, NULL); if (!obj) return JS_FALSE; *rval = OBJECT_TO_JSVAL(obj); } fun = (JSFunction *) JS_GetPrivate(cx, obj);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -