⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spidermonkey.c

📁 一个很有名的浏览器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* The SpiderMonkey ECMAScript backend. *//* $Id: spidermonkey.c,v 1.147.2.8 2005/04/06 08:59:38 jonas Exp $ */#ifdef HAVE_CONFIG_H#include "config.h"#endif/* For wild SpiderMonkey installations. */#ifdef CONFIG_BEOS#define XP_BEOS#elif CONFIG_OS2#define XP_OS2#elif CONFIG_RISCOS#error Out of luck, buddy!#elif CONFIG_UNIX#define XP_UNIX#elif CONFIG_WIN32#define XP_WIN#endif#include <jsapi.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "elinks.h"#include "bfu/dialog.h"#include "cookies/cookies.h"#include "dialogs/menu.h"#include "dialogs/status.h"#include "document/html/frames.h"#include "document/document.h"#include "document/forms.h"#include "document/view.h"#include "ecmascript/ecmascript.h"#include "ecmascript/spidermonkey.h"#include "intl/gettext/libintl.h"#include "lowlevel/select.h"#include "lowlevel/sysname.h"#include "osdep/newwin.h"#include "protocol/http/http.h"#include "protocol/uri.h"#include "sched/task.h"#include "terminal/tab.h"#include "terminal/terminal.h"#include "util/conv.h"#include "util/string.h"#include "viewer/text/draw.h"#include "viewer/text/form.h"#include "viewer/text/link.h"#include "viewer/text/vs.h"/*** Global methods *//* TODO? Are there any which need to be implemented? *//*** Classes */enum prop_type {	JSPT_UNDEF,	JSPT_INT,	JSPT_DOUBLE,	JSPT_STRING,	JSPT_ASTRING,	JSPT_BOOLEAN,	JSPT_OBJECT,};struct jsval_property {	enum prop_type type;	union {		int boolean;		int number;		jsdouble floatnum;		JSObject *object;		unsigned char *string;	} value;};static voidset_prop_undef(struct jsval_property *prop){	memset(prop, 'J', sizeof(struct jsval_property)); /* Active security ;) */	prop->type = JSPT_UNDEF;}static voidset_prop_object(struct jsval_property *prop, JSObject *object){	prop->value.object = object;	prop->type = JSPT_OBJECT;}static voidset_prop_boolean(struct jsval_property *prop, int boolean){	prop->value.boolean = boolean;	prop->type = JSPT_BOOLEAN;}static voidset_prop_string(struct jsval_property *prop, unsigned char *string){	prop->value.string = string;	prop->type = JSPT_STRING;}static voidset_prop_astring(struct jsval_property *prop, unsigned char *string){	prop->value.string = string;	prop->type = JSPT_ASTRING;}static voidset_prop_int(struct jsval_property *prop, int number){	prop->value.number = number;	prop->type = JSPT_INT;}#if 0 /* not yet used. */static voidset_prop_double(struct jsval_property *prop, jsdouble floatnum){	prop->value.floatnum = floatnum;	prop->type = JSPT_DOUBLE;}#endifstatic voidvalue_to_jsval(JSContext *ctx, jsval *vp, struct jsval_property *prop){	switch (prop->type) {	case JSPT_STRING:	case JSPT_ASTRING:		if (!prop->value.string) {			*vp = JSVAL_NULL;			break;		}		*vp = STRING_TO_JSVAL(JS_NewStringCopyZ(ctx, prop->value.string));		if (prop->type == JSPT_ASTRING)			mem_free(prop->value.string);		break;	case JSPT_BOOLEAN:		*vp = BOOLEAN_TO_JSVAL(prop->value.boolean);		break;	case JSPT_DOUBLE:		*vp = DOUBLE_TO_JSVAL(prop->value.floatnum);		break;	case JSPT_INT:		*vp = INT_TO_JSVAL(prop->value.number);		break;	case JSPT_OBJECT:		*vp = OBJECT_TO_JSVAL(prop->value.object);		break;	case JSPT_UNDEF:	default:		*vp = JSVAL_NULL;		break;	}}union jsval_union {	jsint boolean;	jsdouble *number;	unsigned char *string;};static voidjsval_to_value(JSContext *ctx, jsval *vp, JSType type, union jsval_union *var){	jsval val;	if (JS_ConvertValue(ctx, *vp, type, &val) == JS_FALSE) {		switch (type) {		case JSTYPE_BOOLEAN:			var->boolean = JS_FALSE;			break;		case JSTYPE_NUMBER:			var->number = NULL;			break;		case JSTYPE_STRING:			var->string = NULL;			break;		case JSTYPE_VOID:		case JSTYPE_OBJECT:		case JSTYPE_FUNCTION:		case JSTYPE_LIMIT:		default:			INTERNAL("Invalid type %d in jsval_to_value()", type);			break;		}		return;	}	switch (type) {	case JSTYPE_BOOLEAN:		var->boolean = JSVAL_TO_BOOLEAN(val);		break;	case JSTYPE_NUMBER:		var->number = JSVAL_TO_DOUBLE(val);		break;	case JSTYPE_STRING:		var->string = JS_GetStringBytes(JS_ValueToString(ctx, val));		break;	case JSTYPE_VOID:	case JSTYPE_OBJECT:	case JSTYPE_FUNCTION:	case JSTYPE_LIMIT:	default:		INTERNAL("Invalid type %d in jsval_to_value()", type);		break;	}}static JSBool window_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static JSBool window_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp);static const JSClass window_class = {	"window",	JSCLASS_HAS_PRIVATE,	JS_PropertyStub, JS_PropertyStub,	window_get_property, window_set_property,	JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub};enum window_prop {	JSP_WIN_CLOSED,	JSP_WIN_PARENT,	JSP_WIN_SELF,	JSP_WIN_TOP,};/* "location" is special because we need to simulate "location.href" * when the code is asking directly for "location". We do not register * it as a "known" property since that was yielding strange bugs * (SpiderMonkey was still asking us about the "location" string after * assigning to it once), instead we do just a little string * comparing. */static const JSPropertySpec window_props[] = {	{ "closed",	JSP_WIN_CLOSED,	JSPROP_ENUMERATE | JSPROP_READONLY },	{ "parent",	JSP_WIN_PARENT,	JSPROP_ENUMERATE | JSPROP_READONLY },	{ "self",	JSP_WIN_SELF,	JSPROP_ENUMERATE | JSPROP_READONLY },	{ "top",	JSP_WIN_TOP,	JSPROP_ENUMERATE | JSPROP_READONLY },	{ "window",	JSP_WIN_SELF,	JSPROP_ENUMERATE | JSPROP_READONLY },	{ NULL }};static JSObject *try_resolve_frame(struct document_view *doc_view, unsigned char *id){	struct session *ses = doc_view->session;	struct frame *target;	assert(ses);	target = ses_find_frame(ses, id);	if (!target) return NULL;	if (target->vs.ecmascript_fragile)		ecmascript_reset_state(&target->vs);	if (!target->vs.ecmascript) return NULL;	return JS_GetGlobalObject(target->vs.ecmascript->backend_data);}#if 0static struct frame_desc *find_child_frame(struct document_view *doc_view, struct frame_desc *tframe){	struct frameset_desc *frameset = doc_view->document->frame_desc;	int i;	if (!frameset)		return NULL;	for (i = 0; i < frameset->n; i++) {		struct frame_desc *frame = &frameset->frame_desc[i];		if (frame == tframe)			return frame;	}	return NULL;}#endifstatic JSBoolwindow_get_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp){	struct view_state *vs = JS_GetPrivate(ctx, obj);	struct jsval_property prop;	set_prop_undef(&prop);	/* No need for special window.location measurements - when	 * location is then evaluated in string context, toString()	 * is called which we overrode for that class below, so	 * everything's fine. */	if (JSVAL_IS_STRING(id)) {		struct document_view *doc_view = vs->doc_view;		JSObject *obj;		union jsval_union v;		jsval_to_value(ctx, &id, JSTYPE_STRING, &v);		obj = try_resolve_frame(doc_view, v.string);		/* TODO: Try other lookups (mainly element lookup) until		 * something yields data. */		if (!obj) return JS_TRUE;		set_prop_object(&prop, obj);		goto convert;	} else if (!JSVAL_IS_INT(id))		return JS_TRUE;	switch (JSVAL_TO_INT(id)) {	case JSP_WIN_CLOSED:		/* TODO: It will be a major PITA to implement this properly.		 * Well, perhaps not so much if we introduce reference tracking		 * for (struct session)? Still... --pasky */		set_prop_boolean(&prop, 0);		break;	case JSP_WIN_SELF:		set_prop_object(&prop, obj);		break;	case JSP_WIN_PARENT:		/* XXX: It would be nice if the following worked, yes.		 * The problem is that we get called at the point where		 * document.frame properties are going to be mostly NULL.		 * But the problem is deeper because at that time we are		 * yet building scrn_frames so our parent might not be there		 * yet (XXX: is this true?). The true solution will be to just		 * have struct document_view *(document_view.parent). --pasky */		/* FIXME: So now we alias window.parent to window.top, which is		 * INCORRECT but works for the most common cases of just two		 * frames. Better something than nothing. */#if 0	{		/* This is horrible. */		struct document_view *doc_view = vs->doc_view;		struct session *ses = doc_view->session;		struct frame_desc *frame = doc_view->document->frame;		if (!ses->doc_view->document->frame_desc) {			INTERNAL("Looking for parent but there're no frames.");			break;		}		assert(frame);		doc_view = ses->doc_view;		if (find_child_frame(doc_view, frame))			goto found_parent;		foreach (doc_view, ses->scrn_frames) {			if (find_child_frame(doc_view, frame))				goto found_parent;		}		INTERNAL("Cannot find frame %s parent.",doc_view->name);		break;found_parent:		some_domain_security_check();		if (doc_view->vs.ecmascript_fragile)			ecmascript_reset_state(&doc_view->vs);		assert(doc_view->ecmascript);		set_prop_object(&prop, JS_GetGlobalObject(doc_view->ecmascript->backend_data));		break;	}#endif	case JSP_WIN_TOP:	{		struct document_view *doc_view = vs->doc_view;		struct document_view *top_view = doc_view->session->doc_view;		JSObject *newjsframe;		assert(top_view && top_view->vs);		if (top_view->vs->ecmascript_fragile)			ecmascript_reset_state(top_view->vs);		if (!top_view->vs->ecmascript) break;		newjsframe = JS_GetGlobalObject(top_view->vs->ecmascript->backend_data);		/* Keep this unrolled this way. Will have to check document.domain		 * JS property. */		/* Note that this check is perhaps overparanoid. If top windows		 * is alien but some other child window is not, we should still		 * let the script walk thru. That'd mean moving the check to		 * other individual properties in this switch. */		if (compare_uri(vs->uri, top_view->vs->uri, URI_HOST))			set_prop_object(&prop, newjsframe);		else			/****X*X*X*** SECURITY VIOLATION! RED ALERT, SHIELDS UP! ***X*X*X****\			|* (Pasky was apparently looking at the Links2 JS code   .  ___ ^.^ *|			\* for too long.)                                        `.(,_,)\o/ */			set_prop_undef(&prop);		break;	}	default:		INTERNAL("Invalid ID %d in window_get_property().", JSVAL_TO_INT(id));		return JS_TRUE;	}convert:	value_to_jsval(ctx, vp, &prop);	return JS_TRUE;}static void location_goto(struct document_view *doc_view, unsigned char *url);static JSBoolwindow_set_property(JSContext *ctx, JSObject *obj, jsval id, jsval *vp){	struct view_state *vs = JS_GetPrivate(ctx, obj);	union jsval_union v;	if (JSVAL_IS_STRING(id)) {		jsval_to_value(ctx, &id, JSTYPE_STRING, &v);		if (!strcmp(v.string, "location")) {			struct document_view *doc_view = vs->doc_view;			jsval_to_value(ctx, vp, JSTYPE_STRING, &v);			location_goto(doc_view, v.string);			/* Do NOT touch our .location property, evil			 * SpiderMonkey!! */			return JS_FALSE;		}		return JS_TRUE;	} else if (!JSVAL_IS_INT(id))		return JS_TRUE;	switch (JSVAL_TO_INT(id)) {	default:		INTERNAL("Invalid ID %d in window_set_property().", JSVAL_TO_INT(id));		return JS_TRUE;	}	return JS_TRUE;}static JSBool window_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static JSBool window_open(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval);static const JSFunctionSpec window_funcs[] = {	{ "alert",	window_alert,		1 },	{ "open",	window_open,		3 },	{ NULL }};static JSBoolwindow_alert(JSContext *ctx, JSObject *obj, uintN argc, jsval *argv, jsval *rval){	struct view_state *vs = JS_GetPrivate(ctx, obj);	union jsval_union v;	struct jsval_property prop;	set_prop_undef(&prop);	if (argc != 1)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -