📄 spidermonkey.c
字号:
{ if (!fv->ecmascript_obj) { /* jsdoc ('document') is fv's parent */ /* FIXME: That is NOT correct since the real containing element * should be its parent, but gimme DOM first. --pasky */ JSObject *jsform = JS_NewObject(ctx, (JSClass *) &form_class, NULL, jsdoc); JS_DefineProperties(ctx, jsform, (JSPropertySpec *) form_props); JS_DefineFunctions(ctx, jsform, (JSFunctionSpec *) form_funcs); JS_SetPrivate(ctx, jsform, fv); fv->ecmascript_obj = jsform; } return fv->ecmascript_obj;}static JSBool forms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static const JSClass forms_class = { "forms", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, forms_get_property, JS_PropertyStub, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub};static JSBool forms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static JSBool forms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static const JSFunctionSpec forms_funcs[] = { { "item", forms_item, 1 }, { "namedItem", forms_namedItem, 1 }, { NULL }};/* INTs from 0 up are equivalent to item(INT), so we have to stuff length out * of the way. */enum forms_prop { JSP_FORMS_LENGTH = -1 };static const JSPropertySpec forms_props[] = { { "length", JSP_FORMS_LENGTH, JSPROP_ENUMERATE | JSPROP_READONLY}, { NULL }};static JSBoolforms_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp){ JSObject *parent_doc = JS_GetParent(ctx, obj); JSObject *parent_win = JS_GetParent(ctx, parent_doc); struct view_state *vs = JS_GetPrivate(ctx, parent_win); struct document_view *doc_view = vs->doc_view; struct document *document = doc_view->document; struct jsval_property prop; set_prop_undef(&prop); if (JSVAL_IS_STRING(id)) { forms_namedItem(ctx, obj, 1, &id, vp); return JS_TRUE; } else if (!JSVAL_IS_INT(id)) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case JSP_FORMS_LENGTH: { struct form *form; int counter = 0; foreach (form, document->forms) counter++; set_prop_int(&prop, counter); break; } default: /* Array index. */ forms_item(ctx, obj, 1, &id, vp); return JS_TRUE; } value_to_jsval(ctx, vp, &prop); return JS_TRUE;}static JSBoolforms_item(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSObject *parent_doc = JS_GetParent(ctx, obj); JSObject *parent_win = JS_GetParent(ctx, parent_doc); struct view_state *vs = JS_GetPrivate(ctx, parent_win); struct form_view *fv; union jsval_union v; int counter = -1; int index; struct jsval_property prop; set_prop_undef(&prop); if (argc != 1) return JS_TRUE; jsval_to_value(ctx, &argv[0], JSTYPE_STRING, &v); index = atol(v.string); foreach (fv, vs->forms) { counter++; if (counter == index) { set_prop_object(&prop, get_form_object(ctx, parent_doc, fv)); value_to_jsval(ctx, rval, &prop); return JS_TRUE; } } return JS_TRUE;}static JSBoolforms_namedItem(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ JSObject *parent_doc = JS_GetParent(ctx, obj); JSObject *parent_win = JS_GetParent(ctx, parent_doc); struct view_state *vs = JS_GetPrivate(ctx, parent_win); struct document_view *doc_view = vs->doc_view; struct document *document = doc_view->document; struct form *form; union jsval_union v; struct jsval_property prop; set_prop_undef(&prop); if (argc != 1) return JS_TRUE; jsval_to_value(ctx, &argv[0], JSTYPE_STRING, &v); if (!v.string || !*v.string) return JS_TRUE; foreach (form, document->forms) { if (form->name && !strcasecmp(v.string, form->name)) { set_prop_object(&prop, get_form_object(ctx, parent_doc, find_form_view(doc_view, form))); value_to_jsval(ctx, rval, &prop); return JS_TRUE; } } return JS_TRUE;}static JSBool document_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static JSBool document_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static const JSClass document_class = { "document", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, document_get_property, document_set_property, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub};enum document_prop { JSP_DOC_REF, JSP_DOC_TITLE, JSP_DOC_URL };/* "cookie" is special; it isn't a regular property but we channel it to the * cookie-module. XXX: Would it work if "cookie" was defined in this array? */static const JSPropertySpec document_props[] = { { "location", JSP_DOC_URL, JSPROP_ENUMERATE }, { "referrer", JSP_DOC_REF, JSPROP_ENUMERATE | JSPROP_READONLY }, { "title", JSP_DOC_TITLE, JSPROP_ENUMERATE }, /* TODO: Charset? */ { "url", JSP_DOC_URL, JSPROP_ENUMERATE }, { NULL }};static JSBooldocument_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 document *document = doc_view->document; struct session *ses = doc_view->session; struct jsval_property prop; set_prop_undef(&prop); if (JSVAL_IS_STRING(id)) { struct form *form; union jsval_union v; jsval_to_value(ctx, &id, JSTYPE_STRING, &v);#ifdef CONFIG_COOKIES if (!strcmp(v.string, "cookie")) { struct string *cookies = send_cookies(vs->uri); if (cookies) { static unsigned char cookiestr[1024]; strncpy(cookiestr, cookies->source, 1024); done_string(cookies); set_prop_string(&prop, cookiestr); goto convert; } }#endif foreach (form, document->forms) { if (!form->name || strcasecmp(v.string, form->name)) continue; set_prop_object(&prop, get_form_object(ctx, obj, find_form_view(doc_view, form))); goto convert; } return JS_TRUE; } else if (!JSVAL_IS_INT(id)) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case JSP_DOC_REF: switch (get_opt_int("protocol.http.referer.policy")) { case REFERER_NONE: /* oh well */ break; case REFERER_FAKE: set_prop_string(&prop, get_opt_str("protocol.http.referer.fake")); break; case REFERER_TRUE: /* XXX: Encode as in add_url_to_httset_prop_string(&prop, ) ? --pasky */ if (ses->referrer) { set_prop_astring(&prop, get_uri_string(ses->referrer, URI_HTTP_REFERRER)); } break; case REFERER_SAME_URL: set_prop_astring(&prop, get_uri_string(document->uri, URI_HTTP_REFERRER)); break; } break; case JSP_DOC_TITLE: set_prop_string(&prop, document->title); break; case JSP_DOC_URL: set_prop_astring(&prop, get_uri_string(document->uri, URI_ORIGINAL)); break; default: INTERNAL("Invalid ID %d in document_get_property().", JSVAL_TO_INT(id)); return JS_TRUE; }convert: value_to_jsval(ctx, vp, &prop); return JS_TRUE;}static JSBooldocument_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 document *document = doc_view->document; union jsval_union v; if (JSVAL_IS_STRING(id)) { jsval_to_value(ctx, &id, JSTYPE_STRING, &v);#ifdef CONFIG_COOKIES if (!strcmp(v.string, "cookie")) { jsval_to_value(ctx, vp, JSTYPE_STRING, &v); set_cookie(vs->uri, v.string); /* Do NOT touch our .cookie property, evil * SpiderMonkey!! */ return JS_FALSE; }#endif return JS_TRUE; } else if (!JSVAL_IS_INT(id)) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case JSP_DOC_TITLE: jsval_to_value(ctx, vp, JSTYPE_STRING, &v); if (document->title) mem_free(document->title); document->title = stracpy(v.string); break; case JSP_DOC_URL: /* According to the specs this should be readonly but some * broken sites still assign to it (i.e. * http://www.e-handelsfonden.dk/validering.asp?URL=www.polyteknisk.dk). * So emulate window.location. */ jsval_to_value(ctx, vp, JSTYPE_STRING, &v); location_goto(doc_view, v.string); break; } return JS_TRUE;}static JSBool document_write(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static const JSFunctionSpec document_funcs[] = { { "write", document_write, 1 }, { NULL }};static JSBooldocument_write(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){#ifdef CONFIG_LEDS struct ecmascript_interpreter *interpreter = JS_GetContextPrivate(ctx);#endif struct jsval_property prop; set_prop_boolean(&prop, 0); /* XXX: I don't know about you, but I have *ENOUGH* of those 'Undefined * function' errors, I want to see just the useful ones. So just * lighting a led and going away, no muss, no fuss. --pasky */ /* TODO: Perhaps we can introduce ecmascript.error_report_unsupported * -> "Show information about the document using some valid, * nevertheless unsupported methods/properties." --pasky too */#ifdef CONFIG_LEDS interpreter->vs->doc_view->session->status.ecmascript_led->value = 'J';#endif value_to_jsval(ctx, rval, &prop); return JS_TRUE;}static JSBool location_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static JSBool location_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static const JSClass location_class = { "location", JSCLASS_HAS_PRIVATE, JS_PropertyStub, JS_PropertyStub, location_get_property, location_set_property, JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub};enum location_prop { JSP_LOC_HREF };static const JSPropertySpec location_props[] = { { "href", JSP_LOC_HREF, JSPROP_ENUMERATE }, { NULL }};static JSBoollocation_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 jsval_property prop; set_prop_undef(&prop); if (!JSVAL_IS_INT(id)) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case JSP_LOC_HREF: set_prop_astring(&prop, get_uri_string(vs->uri, URI_ORIGINAL)); break; default: INTERNAL("Invalid ID %d in location_get_property().", JSVAL_TO_INT(id)); return JS_TRUE; } value_to_jsval(ctx, vp, &prop); return JS_TRUE;}static JSBoollocation_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; union jsval_union v; if (!JSVAL_IS_INT(id)) return JS_TRUE; switch (JSVAL_TO_INT(id)) { case JSP_LOC_HREF: jsval_to_value(ctx, vp, JSTYPE_STRING, &v); location_goto(doc_view, v.string); break; } return JS_TRUE;}static JSBool location_toString(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static const JSFunctionSpec location_funcs[] = { { "toString", location_toString, 0 }, { "toLocaleString", location_toString, 0 }, { NULL }};static JSBoollocation_toString(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){ return JS_GetProperty(ctx, obj, "href", rval);}struct delayed_goto { /* It might look more convenient to pass doc_view around but it could * disappear during wild dances inside of frames or so. */ struct view_state *vs; struct uri *uri;};static voiddelayed_goto(void *data){ struct delayed_goto *deg = data; assert(deg); if (deg->vs->doc_view) { goto_uri_frame(deg->vs->doc_view->session, deg->uri, deg->vs->doc_view->name, CACHE_MODE_NORMAL); } done_uri(deg->uri); mem_free(deg);}static voidlocation_goto(struct document_view *doc_view, unsigned char *url){ unsigned char *new_abs_url; struct uri *new_uri; struct delayed_goto *deg; new_abs_url = join_urls(doc_view->document->uri, trim_chars(url, ' ', 0)); if (!new_abs_url) return; new_uri = get_uri(new_abs_url, 0); mem_free(new_abs_url); if (!new_uri) return; deg = mem_calloc(1, sizeof(*deg)); if (!deg) { done_uri(new_uri); return; } assert(doc_view->vs); deg->vs = doc_view->vs; deg->uri = new_uri; /* It does not seem to be very safe inside of frames to * call goto_uri() right away. */ register_bottom_half((void (*)(void *)) delayed_goto, deg);}static JSBool unibar_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static JSBool unibar_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static const JSClass menubar_class = { "menubar",
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -