📄 spidermonkey.c
字号:
JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, unibar_get_property, unibar_set_property, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub};static const JSClass statusbar_class = { "statusbar", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, unibar_get_property, unibar_set_property, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub};enum unibar_prop { JSP_UNIBAR_VISIBLE };static const JSPropertySpec unibar_props[] = { { "visible", JSP_UNIBAR_VISIBLE, JSPROP_ENUMERATE }, { NULL }};static JSBoolunibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp){ JSObject *parent = JS_GetParent(ctx, obj); struct view_state *vs = JS_GetPrivate(ctx, parent); struct document_view *doc_view = vs->doc_view; struct session_status *status = &doc_view->session->status; unsigned char *bar = JS_GetPrivate(ctx, obj); struct jsval_property prop; set_prop_undef(&prop); if (!JSVAL_IS_INT(id)) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case JSP_UNIBAR_VISIBLE:#define unibar_fetch(bar) \ set_prop_boolean(&prop, status->force_show_##bar##_bar >= 0 \ ? status->force_show_##bar##_bar \ : status->show_##bar##_bar) switch (*bar) { case 's': unibar_fetch(status); break; case 't': unibar_fetch(title); break; default: set_prop_boolean(&prop, 0); break; }#undef unibar_fetch break; default: INTERNAL("Invalid ID %d in unibar_get_property().", JSVAL_TO_INT(id)); return JS_TRUE; } value_to_jsval(ctx, vp, &prop); return JS_TRUE;}static JSBoolunibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp){ JSObject *parent = JS_GetParent(ctx, obj); struct view_state *vs = JS_GetPrivate(ctx, parent); struct document_view *doc_view = vs->doc_view; struct session_status *status = &doc_view->session->status; unsigned char *bar = JS_GetPrivate(ctx, obj); union jsval_union v; if (!JSVAL_IS_INT(id)) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case JSP_UNIBAR_VISIBLE: jsval_to_value(ctx, vp, JSTYPE_BOOLEAN, &v);#define unibar_set(bar) \ status->force_show_##bar##_bar = v.boolean; switch (*bar) { case 's': unibar_set(status); break; case 't': unibar_set(title); break; default: v.boolean = 0; break; } register_bottom_half((void (*)(void*)) update_status, NULL);#undef unibar_set break; default: INTERNAL("Invalid ID %d in unibar_set_property().", JSVAL_TO_INT(id)); return JS_TRUE; } return JS_TRUE;}static JSBool navigator_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static const JSClass navigator_class = { "navigator", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, navigator_get_property, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub};enum navigator_prop { JSP_NAVIGATOR_APP_CODENAME, JSP_NAVIGATOR_APP_NAME, JSP_NAVIGATOR_APP_VERSION, JSP_NAVIGATOR_LANGUAGE, /* JSP_NAVIGATOR_MIME_TYPES, */ JSP_NAVIGATOR_PLATFORM, /* JSP_NAVIGATOR_PLUGINS, */ JSP_NAVIGATOR_USER_AGENT,};static const JSPropertySpec navigator_props[] = { { "appCodeName", JSP_NAVIGATOR_APP_CODENAME, JSPROP_ENUMERATE | JSPROP_READONLY }, { "appName", JSP_NAVIGATOR_APP_NAME, JSPROP_ENUMERATE | JSPROP_READONLY }, { "appVersion", JSP_NAVIGATOR_APP_VERSION, JSPROP_ENUMERATE | JSPROP_READONLY }, { "language", JSP_NAVIGATOR_LANGUAGE, JSPROP_ENUMERATE | JSPROP_READONLY }, { "platform", JSP_NAVIGATOR_PLATFORM, JSPROP_ENUMERATE | JSPROP_READONLY }, { "userAgent", JSP_NAVIGATOR_USER_AGENT, JSPROP_ENUMERATE | JSPROP_READONLY }, { NULL }};static JSBoolnavigator_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp){ struct jsval_property prop; set_prop_undef(&prop); if (!JSVAL_IS_INT(id)) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case JSP_NAVIGATOR_APP_CODENAME: set_prop_string(&prop, "Mozilla"); /* More like a constant nowadays. */ break; case JSP_NAVIGATOR_APP_NAME: /* This evil hack makes the compatibility checking .indexOf() * code find what it's looking for. */ set_prop_string(&prop, "ELinks (roughly compatible with Netscape Navigator, Mozilla and Microsoft Internet Explorer)"); break; case JSP_NAVIGATOR_APP_VERSION: set_prop_string(&prop, VERSION); break; case JSP_NAVIGATOR_LANGUAGE:#ifdef ENABLE_NLS if (get_opt_bool("protocol.http.accept_ui_language")) set_prop_string(&prop, language_to_iso639(current_language)); else#endif set_prop_undef(&prop); break; case JSP_NAVIGATOR_PLATFORM: set_prop_string(&prop, system_name); break; case JSP_NAVIGATOR_USER_AGENT: { /* FIXME: Code duplication. */ unsigned char *optstr = get_opt_str("protocol.http.user_agent"); if (*optstr && strcmp(optstr, " ")) { unsigned char *ustr, ts[64] = ""; static unsigned char custr[256]; if (!list_empty(terminals)) { unsigned int tslen = 0; struct terminal *term = terminals.prev; ulongcat(ts, &tslen, term->width, 3, 0); ts[tslen++] = 'x'; ulongcat(ts, &tslen, term->height, 3, 0); } ustr = subst_user_agent(optstr, VERSION_STRING, system_name, ts); if (ustr) { safe_strncpy(custr, ustr, 256); mem_free(ustr); set_prop_string(&prop, custr); } else{ set_prop_undef(&prop); } } } break; default: INTERNAL("Invalid ID %d in navigator_get_property().", JSVAL_TO_INT(id)); return JS_TRUE; } value_to_jsval(ctx, vp, &prop); return JS_TRUE;}/*** The ELinks interface */static JSRuntime *jsrt;static voiderror_reporter(JSContext *ctx, const char *message, JSErrorReport *report){ struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); struct terminal *term; unsigned char *strict, *exception, *warning, *error; struct string msg; assert(interpreter && interpreter->vs && interpreter->vs->doc_view && interpreter->vs->doc_view->session && interpreter->vs->doc_view->session->tab); if_assert_failed goto reported; term = interpreter->vs->doc_view->session->tab->term;#ifdef CONFIG_LEDS interpreter->vs->doc_view->session->status.ecmascript_led->value = 'J';#endif if (!get_opt_bool("ecmascript.error_reporting") || !init_string(&msg)) goto reported; strict = JSREPORT_IS_STRICT(report->flags) ? " strict" : ""; exception = JSREPORT_IS_EXCEPTION(report->flags) ? " exception" : ""; warning = JSREPORT_IS_WARNING(report->flags) ? " warning" : ""; error = !report->flags ? " error" : ""; add_format_to_string(&msg, _("A script embedded in the current " "document raised the following%s%s%s%s", term), strict, exception, warning, error); add_to_string(&msg, ":\n\n"); add_to_string(&msg, message); if (report->linebuf && report->tokenptr) { int pos = report->tokenptr - report->linebuf; add_format_to_string(&msg, "\n\n%s\n.%*s^%*s.", report->linebuf, pos - 2, " ", strlen(report->linebuf) - pos - 1, " "); } info_box(term, MSGBOX_FREE_TEXT, N_("JavaScript Error"), ALIGN_CENTER, msg.source);reported: /* Im clu'les. --pasky */ JS_ClearPendingException(ctx);}static JSBoolsafeguard(JSContext *ctx, JSScript *script){ struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx); int max_exec_time = get_opt_int("ecmascript.max_exec_time"); if (time(NULL) - interpreter->exec_start > max_exec_time) { struct terminal *term = interpreter->vs->doc_view->session->tab->term; /* A killer script! Alert! */ info_box(term, MSGBOX_FREE_TEXT, N_("JavaScript Emergency"), ALIGN_LEFT, msg_text(term, N_("A script embedded in the current document was running\n" "for more than %d seconds. This probably means there is\n" "a bug in the script and it could have halted the whole\n" "ELinks, so the script execution was interrupted."), max_exec_time)); return JS_FALSE; } return JS_TRUE;}static voidsetup_safeguard(struct ecmascript_interpreter *interpreter, JSContext *ctx){ interpreter->exec_start = time(NULL); JS_SetBranchCallback(ctx, safeguard);}voidspidermonkey_init(void){ jsrt = JS_NewRuntime(0x400000UL);}voidspidermonkey_done(void){ JS_DestroyRuntime(jsrt); JS_ShutDown();}void *spidermonkey_get_interpreter(struct ecmascript_interpreter *interpreter){ JSContext *ctx; JSObject *window_obj, *document_obj, *forms_obj, *location_obj, *statusbar_obj, *menubar_obj, *navigator_obj; assert(interpreter); ctx = JS_NewContext(jsrt, 8192 /* Stack allocation chunk size */); if (!ctx) return NULL; interpreter->backend_data = ctx; JS_SetContextPrivate(ctx, interpreter); /* TODO: Make JSOPTION_STRICT and JSOPTION_WERROR configurable. */#ifndef JSOPTION_COMPILE_N_GO#define JSOPTION_COMPILE_N_GO 0 /* Older SM versions don't have it. */#endif /* XXX: JSOPTION_COMPILE_N_GO will go (will it?) when we implement * some kind of bytecode cache. (If we will ever do that.) */ JS_SetOptions(ctx, JSOPTION_VAROBJFIX | JSOPTION_COMPILE_N_GO); JS_SetErrorReporter(ctx, error_reporter); window_obj = JS_NewObject(ctx, (JSClass *) &window_class, NULL, NULL); if (!window_obj) { spidermonkey_put_interpreter(interpreter); return NULL; } JS_InitStandardClasses(ctx, window_obj); JS_DefineProperties(ctx, window_obj, (JSPropertySpec *) window_props); JS_DefineFunctions(ctx, window_obj, (JSFunctionSpec *) window_funcs); JS_SetPrivate(ctx, window_obj, interpreter->vs); document_obj = JS_InitClass(ctx, window_obj, NULL, (JSClass *) &document_class, NULL, 0, (JSPropertySpec *) document_props, (JSFunctionSpec *) document_funcs, NULL, NULL); forms_obj = JS_InitClass(ctx, document_obj, NULL, (JSClass *) &forms_class, NULL, 0, (JSPropertySpec *) forms_props, (JSFunctionSpec *) forms_funcs, NULL, NULL); location_obj = JS_InitClass(ctx, window_obj, NULL, (JSClass *) &location_class, NULL, 0, (JSPropertySpec *) location_props, (JSFunctionSpec *) location_funcs, NULL, NULL); menubar_obj = JS_InitClass(ctx, window_obj, NULL, (JSClass *) &menubar_class, NULL, 0, (JSPropertySpec *) unibar_props, NULL, NULL, NULL); JS_SetPrivate(ctx, menubar_obj, "t"); statusbar_obj = JS_InitClass(ctx, window_obj, NULL, (JSClass *) &statusbar_class, NULL, 0, (JSPropertySpec *) unibar_props, NULL, NULL, NULL); JS_SetPrivate(ctx, statusbar_obj, "s"); navigator_obj = JS_InitClass(ctx, window_obj, NULL, (JSClass *) &navigator_class, NULL, 0, (JSPropertySpec *) navigator_props, NULL, NULL, NULL); return ctx;}voidspidermonkey_put_interpreter(struct ecmascript_interpreter *interpreter){ JSContext *ctx; assert(interpreter); ctx = interpreter->backend_data; JS_DestroyContext(ctx); interpreter->backend_data = NULL;}voidspidermonkey_eval(struct ecmascript_interpreter *interpreter, struct string *code){ JSContext *ctx; jsval rval; assert(interpreter); ctx = interpreter->backend_data; setup_safeguard(interpreter, ctx); JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), code->source, code->length, "", 0, &rval);}unsigned char *spidermonkey_eval_stringback(struct ecmascript_interpreter *interpreter, struct string *code){ JSContext *ctx; jsval rval; union jsval_union v; assert(interpreter); ctx = interpreter->backend_data; setup_safeguard(interpreter, ctx); if (JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), code->source, code->length, "", 0, &rval) == JS_FALSE) { return NULL; } if (JSVAL_IS_VOID(rval)) { /* Undefined value. */ return NULL; } jsval_to_value(ctx, &rval, JSTYPE_STRING, &v); if (!v.string) return NULL; return stracpy(v.string);}intspidermonkey_eval_boolback(struct ecmascript_interpreter *interpreter, struct string *code){ JSContext *ctx; jsval rval; union jsval_union v; assert(interpreter); ctx = interpreter->backend_data; setup_safeguard(interpreter, ctx); if (JS_EvaluateScript(ctx, JS_GetGlobalObject(ctx), code->source, code->length, "", 0, &rval) == JS_FALSE) { return -1; } if (JSVAL_IS_VOID(rval)) { /* Undefined value. */ return -1; } jsval_to_value(ctx, &rval, JSTYPE_BOOLEAN, &v); return v.boolean;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -