* [Edbrowse-dev] [PATCH 1/2] Initial version of jsloc.cpp (built against mozjs 1.85) also rename objClass to obj_class in jsdom.cpp
@ 2013-12-24 18:57 Adam Thompson
0 siblings, 0 replies; only message in thread
From: Adam Thompson @ 2013-12-24 18:57 UTC (permalink / raw)
To: edbrowse-dev
---
src/jsdom.cpp | 8 +-
src/jsloc.cpp | 1020 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 1024 insertions(+), 4 deletions(-)
create mode 100644 src/jsloc.cpp
diff --git a/src/jsdom.cpp b/src/jsdom.cpp
index b2ff51a..5783125 100644
--- a/src/jsdom.cpp
+++ b/src/jsdom.cpp
@@ -746,7 +746,7 @@ static JSClass option_class = {
};
struct DOMCLASS {
- JSClass *objClass;
+ JSClass *obj_class;
JSFunctionSpec *methods;
JSNative constructor;
int nargs;
@@ -886,8 +886,8 @@ createJavaContext(void)
establish_property_string((JSObject *) jwin, "name", "unspecifiedFrame", eb_false);
/* Other classes that we'll need. */
- for(i = 0; domClasses[i].objClass; ++i) {
- JS_InitClass(jcx, (JSObject *) jwin, 0, domClasses[i].objClass,
+ for(i = 0; domClasses[i].obj_class; ++i) {
+ JS_InitClass(jcx, (JSObject *) jwin, 0, domClasses[i].obj_class,
domClasses[i].constructor, domClasses[i].nargs,
NULL, domClasses[i].methods, NULL, NULL);
}
@@ -1115,7 +1115,7 @@ domLink(const char *classname, /* instantiate this class */
return 0;
/* find the class */
- for(i = 0; cp = domClasses[i].objClass; ++i)
+ for(i = 0; cp = domClasses[i].obj_class; ++i)
if(stringEqual(cp->name, classname))
break;
diff --git a/src/jsloc.cpp b/src/jsloc.cpp
new file mode 100644
index 0000000..eae7bd9
--- /dev/null
+++ b/src/jsloc.cpp
@@ -0,0 +1,1020 @@
+/* jsloc.c
+* Javascript support, the URL class and the location object.
+ * The cookie string, and other things with get/set side effects.
+* Copyright (c) Karl Dahlke, 2008
+* This file is part of the edbrowse project, released under GPL.
+*/
+
+#include "eb.h"
+
+#include "js.h"
+using namespace std;
+
+/* jsprf.h is not publically visible on some systems,
+so I can't #include it here.
+Instead, I'll declare the needed prototype myself, and hope it is consistent
+with whatever smjs you are using. */
+extern
+JS_PUBLIC_API(char *)
+JS_smprintf(const char *fmt, ...);
+/* same goes for this one */
+extern JS_PUBLIC_API(void) JS_smprintf_free(char *mem);
+
+#define PROP_FIXED (JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
+
+
+/*********************************************************************
+The URL class, and the associated window.location object, is tricky,
+with lots of interacting properties and setter functions.
+*********************************************************************/
+
+static const char *emptyParms[] = { 0 };
+static jsval emptyArgs[] = { 0 };
+
+static void
+ url_initialize(const char *url, eb_bool readonly, eb_bool exclude_href);
+
+const char *
+stringize(jsval v)
+{
+ static char buf[24];
+ static char *dynamic;
+ int n;
+ jsdouble d;
+ if(JSVAL_IS_STRING(v)) {
+ if(dynamic)
+ JS_free(jcx, dynamic);
+ dynamic = our_JSEncodeString(JSVAL_TO_STRING(v));
+ return dynamic;
+ }
+ if(JSVAL_IS_INT(v)) {
+ n = JSVAL_TO_INT(v);
+ sprintf(buf, "%d", n);
+ return buf;
+ }
+ if(JSVAL_IS_DOUBLE(v)) {
+ d = JSVAL_TO_DOUBLE(v);
+ n = d;
+ if(n == d)
+ sprintf(buf, "%d", n);
+ else
+ sprintf(buf, "%lf", d);
+ return buf;
+ }
+/* Sorry, I don't look for object.toString() */
+ return 0; /* failed */
+} /* stringize */
+
+static JSClass url_class = {
+ "URL",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+};
+
+/* To builld path names, host names, etc. */
+static char urlbuffer[512];
+static JSObject *uo; /* the url object */
+static char *uo_href;
+static eb_bool setter_suspend;
+
+/* Are we modifying window.location? */
+/*Return false if we are, because that will put a stop to javascript. */
+static eb_bool
+isWinLoc(void)
+{
+ if(uo != jwloc && uo != jdloc) {
+ nzFree(uo_href);
+ uo_href = 0;
+ return eb_true;
+ }
+/* This call frees t, or takes it over, so you should not free it here. */
+ gotoLocation(uo_href, (allowRedirection ? 0 : 99), eb_false);
+ uo_href = 0;
+ return eb_false;
+} /* isWinLoc */
+
+/* Converting to a string just pulls out the href property */
+static JSBool
+loc_toString(JSContext * cx, uintN argc, jsval * vp)
+{
+ JSObject *obj = JS_THIS_OBJECT(cx, vp);
+ jsval rval = JS_RVAL(cx, vp);
+ JS_GetProperty(jcx, obj, "href", &rval);
+ JS_SET_RVAL(cx, vp, rval);
+ return JS_TRUE;
+} /* loc_toString */
+
+static JSBool
+loc_reload(JSContext * cx, uintN argc, jsval * vp)
+{
+ const char *s = cw->firstURL;
+ if(s && isURL(s))
+ gotoLocation(cloneString(s), (allowRedirection ? 0 : 99), eb_true);
+ else
+ JS_ReportError(jcx, "location.reload() cannot find a url to refresh");
+ return JS_FALSE;
+} /* loc_reload */
+
+static JSBool
+loc_replace(JSContext * cx, uintN argc, jsval * vp)
+{
+ const char *s;
+ char *ss, *t;
+ jsval *argv = JS_ARGV(cx, vp);
+ if(argc > 0 && JSVAL_IS_STRING(argv[0])) {
+ s = stringize(argv[0]);
+/* I have to copy the string, just so I can run unpercent */
+ ss = cloneString(s);
+ unpercentURL(ss);
+ t = resolveURL(cw->fileName, ss);
+ nzFree(ss);
+/* This call frees t, or takes it over, so you should not free it here. */
+ gotoLocation(t, (allowRedirection ? 0 : 99), eb_true);
+ return JS_FALSE;
+ }
+ JS_ReportError(jcx,
+ "argument to location.replace() does not look like a url");
+ return JS_FALSE;
+} /* loc_replace */
+
+/* Put a url together from its pieces, after something has changed. */
+static void
+build_url(int exception, const char *e)
+{
+ jsval v;
+ const char *prot, *slashes, *host, *pathname, *pathslash, *search, *hash;
+ char *new_url;
+ static const char *const noslashes[] = {
+ "mailto", "telnet", "javascript", 0
+ };
+ setter_suspend = eb_true;
+/* I'm a little worried about the first one being freed while I'm
+ * getting the next one.
+ * I just don't know that much about the js heap. */
+ if(exception == 1)
+ prot = e;
+ else {
+ JS_GetProperty(jcx, uo, "protocol", &v);
+ prot = stringize(v);
+ }
+ slashes = EMPTYSTRING;
+ if(stringInListCI(noslashes, prot) < 0)
+ slashes = "//";
+ if(exception == 2)
+ host = e;
+ else {
+ JS_GetProperty(jcx, uo, "host", &v);
+ host = stringize(v);
+ }
+ if(exception == 3)
+ pathname = e;
+ else {
+ JS_GetProperty(jcx, uo, "pathname", &v);
+ pathname = stringize(v);
+ }
+ pathslash = EMPTYSTRING;
+ if(pathname[0] != '/')
+ pathslash = "/";
+ if(exception == 4)
+ search = e;
+ else {
+ JS_GetProperty(jcx, uo, "search", &v);
+ search = stringize(v);
+ }
+ if(exception == 5)
+ hash = e;
+ else {
+ JS_GetProperty(jcx, uo, "hash", &v);
+ hash = stringize(v);
+ }
+ new_url =
+ JS_smprintf("%s%s%s%s%s%s%s", prot, slashes, host, pathslash, pathname,
+ search, hash);
+ v = STRING_TO_JSVAL(our_JS_NewStringCopyZ(jcx, new_url));
+ JS_SetProperty(jcx, uo, "href", &v);
+/* I want control over this string */
+ uo_href = cloneString(new_url);
+ JS_smprintf_free(new_url);
+ setter_suspend = eb_false;
+} /* build_url */
+
+/* Rebuild host, because hostname or port changed. */
+static void
+build_host(int exception, const char *hostname, int port)
+{
+ jsval v;
+ const char *oldhost;
+ setter_suspend = eb_true;
+ if(exception == 1) {
+ JS_GetProperty(jcx, uo, "port", &v);
+ port = JSVAL_TO_INT(v);
+ } else {
+ JS_GetProperty(jcx, uo, "hostname", &v);
+ hostname = stringize(v);
+ }
+ JS_GetProperty(jcx, uo, "host", &v);
+ oldhost = stringize(v);
+ if(exception == 2 || strchr(oldhost, ':'))
+ sprintf(urlbuffer, "%s:%d", hostname, port);
+ else
+ strcpy(urlbuffer, hostname);
+ if(strlen(urlbuffer) >= sizeof (urlbuffer))
+ i_printfExit(MSG_PortTooLong);
+ v = STRING_TO_JSVAL(our_JS_NewStringCopyZ(jcx, urlbuffer));
+ JS_SetProperty(jcx, uo, "host", &v);
+ setter_suspend = eb_false;
+} /* build_host */
+
+/* define or set a local property */
+static void
+loc_def_set(const char *name, const char *s,
+ JSBool(*setter) (JSContext *, JSObject *, jsid, JSBool, jsval *),
+ jsuint attr)
+{
+ JSBool found;
+ jsval vv;
+ if(s)
+ vv = STRING_TO_JSVAL(our_JS_NewStringCopyZ(jcx, s));
+ else
+ vv = JS_GetEmptyStringValue(jcx);
+ JS_HasProperty(jcx, uo, name, &found);
+ if(found)
+ JS_SetProperty(jcx, uo, name, &vv);
+ else
+ JS_DefineProperty(jcx, uo, name, vv, NULL, setter, attr);
+} /* loc_def_set */
+
+/* Like the above, but using an integer, this is for port only. */
+static void
+loc_def_set_n(const char *name, int port,
+ JSBool(*setter) (JSContext *, JSObject *, jsid, JSBool, jsval *),
+ jsuint attr)
+{
+ JSBool found;
+ jsval vv = INT_TO_JSVAL(port);
+ JS_HasProperty(jcx, uo, name, &found);
+ if(found)
+ JS_SetProperty(jcx, uo, name, &vv);
+ else
+ JS_DefineProperty(jcx, uo, name, vv, NULL, setter, attr);
+} /* loc_def_set_n */
+
+static void
+loc_def_set_part(const char *name, const char *s, int n,
+ JSBool(*setter) (JSContext *, JSObject *, jsid, JSBool, jsval *),
+ jsuint attr)
+{
+ JSBool found;
+ jsval vv;
+ if(s)
+ vv = STRING_TO_JSVAL(our_JS_NewStringCopyN(jcx, s, n));
+ else
+ vv = JS_GetEmptyStringValue(jcx);
+ JS_HasProperty(jcx, uo, name, &found);
+ if(found)
+ JS_SetProperty(jcx, uo, name, &vv);
+ else
+ JS_DefineProperty(jcx, uo, name, vv, NULL, setter, attr);
+} /* loc_def_set_part */
+
+static JSBool
+setter_loc(JSContext * cx, JSObject * obj, jsid id, JSBool strict, jsval * vp)
+{
+ const char *s = stringize(*vp);
+ if(!s) {
+ JS_ReportError(jcx,
+ "window.location is assigned something that I don't understand");
+ } else {
+ char *t;
+/* I have to copy the string, just so I can run unpercent */
+ char *ss = cloneString(s);
+ unpercentURL(ss);
+ t = resolveURL(cw->fileName, ss);
+ nzFree(ss);
+/* This call frees t, or takes it over, so you should not free it here. */
+ gotoLocation(t, (allowRedirection ? 0 : 99), eb_false);
+ }
+/* Return false to stop javascript. */
+/* After all, we're trying to move to a new web page. */
+ return JS_FALSE;
+} /* setter_loc */
+
+static JSBool
+setter_loc_href(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *url = 0;
+ if(setter_suspend)
+ return JS_TRUE;
+ url = stringize(*vp);
+ if(!url)
+ return JS_TRUE;
+ uo = obj;
+ url_initialize(url, eb_false, eb_true);
+ uo_href = cloneString(url);
+ if(uo == jwloc || uo == jdloc) {
+ char *t;
+ unpercentURL(uo_href);
+ t = resolveURL(cw->fileName, uo_href);
+ nzFree(uo_href);
+ uo_href = t;
+ }
+ return isWinLoc();
+} /* setter_loc_href */
+
+static JSBool
+setter_loc_hash(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *e;
+ if(setter_suspend)
+ return JS_TRUE;
+ e = stringize(*vp);
+ uo = obj;
+ build_url(5, e);
+ return isWinLoc();
+} /* setter_loc_hash */
+
+static JSBool
+setter_loc_search(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *e;
+ if(setter_suspend)
+ return JS_TRUE;
+ e = stringize(*vp);
+ uo = obj;
+ build_url(4, e);
+ return isWinLoc();
+} /* setter_loc_search */
+
+static JSBool
+setter_loc_prot(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *e;
+ if(setter_suspend)
+ return JS_TRUE;
+ e = stringize(*vp);
+ uo = obj;
+ build_url(1, e);
+ return isWinLoc();
+} /* setter_loc_prot */
+
+static JSBool
+setter_loc_pathname(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *e;
+ if(setter_suspend)
+ return JS_TRUE;
+ e = stringize(*vp);
+ uo = obj;
+ build_url(3, e);
+ return isWinLoc();
+} /* setter_loc_pathname */
+
+static JSBool
+setter_loc_hostname(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *e;
+ if(setter_suspend)
+ return JS_TRUE;
+ e = stringize(*vp);
+ uo = obj;
+ build_host(1, e, 0);
+ build_url(0, 0);
+ return isWinLoc();
+} /* setter_loc_hostname */
+
+static JSBool
+setter_loc_port(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ int port;
+ if(setter_suspend)
+ return JS_TRUE;
+ port = JSVAL_TO_INT(*vp);
+ uo = obj;
+ build_host(2, 0, port);
+ build_url(0, 0);
+ return isWinLoc();
+} /* setter_loc_port */
+
+static JSBool
+setter_loc_host(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *e, *s;
+ int n;
+ jsval v;
+ if(setter_suspend)
+ return JS_TRUE;
+ e = stringize(*vp);
+ uo = obj;
+ build_url(2, e);
+/* and we have to update hostname and port */
+ setter_suspend = eb_true;
+ s = strchr(e, ':');
+ if(s)
+ n = s - e;
+ else
+ n = strlen(e);
+ v = STRING_TO_JSVAL(our_JS_NewStringCopyN(jcx, e, n));
+ JS_SetProperty(jcx, uo, "hostname", &v);
+ if(s) {
+ v = INT_TO_JSVAL(atoi(s + 1));
+ JS_SetProperty(jcx, uo, "port", &v);
+ }
+ setter_suspend = eb_false;
+ return isWinLoc();
+} /* setter_loc_pathname */
+
+static void
+url_initialize(const char *url, eb_bool readonly, eb_bool exclude_href)
+{
+ int n, port;
+ const char *data;
+ const char *s;
+ const char *pl;
+ jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
+ if(readonly)
+ attr |= JSPROP_READONLY;
+
+ setter_suspend = eb_true;
+
+/* Store the url in location.href */
+ if(!exclude_href) {
+ loc_def_set("href", url, setter_loc_href, attr);
+ }
+
+/* Now make a property for each piece of the url. */
+ if(s = getProtURL(url)) {
+ sprintf(urlbuffer, "%s:", s);
+ if(strlen(urlbuffer) >= sizeof (urlbuffer))
+ i_printfExit(MSG_ProtTooLong);
+ s = urlbuffer;
+ }
+ loc_def_set("protocol", s, setter_loc_prot, attr);
+
+ data = getDataURL(url);
+ s = 0;
+ if(data)
+ s = strchr(data, '#');
+ loc_def_set("hash", s, setter_loc_hash, attr);
+
+ s = getHostURL(url);
+ if(s && !*s)
+ s = 0;
+ loc_def_set("hostname", s, setter_loc_hostname, attr);
+
+ getPortLocURL(url, &pl, &port);
+ loc_def_set_n("port", port, setter_loc_port, attr);
+
+ if(s) { /* this was hostname */
+ strcpy(urlbuffer, s);
+ if(pl)
+ sprintf(urlbuffer + strlen(urlbuffer), ":%d", port);
+ if(strlen(urlbuffer) >= sizeof (urlbuffer))
+ i_printfExit(MSG_PortTooLong);
+ s = urlbuffer;
+ }
+ loc_def_set("host", s, setter_loc_host, attr);
+
+ s = 0;
+ n = 0;
+ getDirURL(url, &s, &pl);
+ if(s) {
+ pl = strpbrk(s, "?\1#");
+ n = pl ? pl - s : strlen(s);
+ if(!n)
+ s = "/", n = 1;
+ }
+ loc_def_set_part("pathname", s, n, setter_loc_pathname, attr);
+
+ s = 0;
+ if(data && (s = strpbrk(data, "?\1")) &&
+ (!(pl = strchr(data, '#')) || pl > s)) {
+ if(pl)
+ n = pl - s;
+ else
+ n = strlen(s);
+ } else {
+/* If we have foo.html#?bla, then ?bla is not the query.
+ * We need to set s to NULL and n to 0, lest we feed invalid data to
+ * spidermonkey. */
+ s = NULL;
+ n = 0;
+ }
+
+ loc_def_set_part("search", s, n, setter_loc_search, attr);
+
+ setter_suspend = eb_false;
+} /* url_initialize */
+
+static JSBool
+url_ctor(JSContext * cx, uintN argc, jsval * vp)
+{
+ const char *url = NULL;
+ const char *s;
+ jsval *argv;
+ JSObject *obj;
+ obj = JS_THIS_OBJECT(cx, vp);
+ argv = JS_ARGV(cx, vp);
+ if(argc && JSVAL_IS_STRING(*argv)) {
+ s = stringize(argv[0]);
+ if(strlen(s))
+ url = s;
+ } /* string argument */
+ uo = obj;
+ url_initialize(url, eb_false, eb_false);
+ return JS_TRUE;
+} /* url_ctor */
+
+static JSFunctionSpec url_methods[] = {
+ {"toString", loc_toString, 0, 0},
+ {0}
+};
+
+void
+initLocationClass(void)
+{
+ JS_InitClass(jcx, (JSObject *) jwin, NULL, &url_class, url_ctor, 1,
+ NULL, url_methods, NULL, NULL);
+} /* initLocationClass */
+
+
+/*********************************************************************
+If js changes the value of an input field in a form,
+this fact has to make it back to the text you are reading, in edbrowse,
+after js returns.
+That requires a special setter function to pass the new value back to the text.
+*********************************************************************/
+
+static JSBool
+setter_value(JSContext * cx, JSObject * obj, jsid id, JSBool strict, jsval * vp)
+{
+ const char *val;
+ if(setter_suspend)
+ return JS_TRUE;
+ val = stringize(*vp);
+ if(!val) {
+ JS_ReportError(jcx,
+ "input.value is assigned something other than a string; this can cause problems when you submit the form.");
+ } else {
+ javaSetsTagVar(obj, val);
+ }
+ return JS_TRUE;
+} /* setter_value */
+
+static JSBool
+setter_checked(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ JSBool b;
+ if(setter_suspend)
+ return JS_TRUE;
+ b = JSVAL_TO_BOOLEAN(*vp);
+ return JS_TRUE;
+} /* setter_checked */
+
+static JSBool
+setter_selected(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ JSBool b;
+ if(setter_suspend)
+ return JS_TRUE;
+ b = JSVAL_TO_BOOLEAN(*vp);
+ return JS_TRUE;
+} /* setter_selected */
+
+static JSBool
+setter_selidx(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ int n;
+ if(setter_suspend)
+ return JS_TRUE;
+ n = JSVAL_TO_INT(*vp);
+ return JS_TRUE;
+} /* setter_selidx */
+
+static JSBool
+getter_cookie(JSContext * cx, JSObject * obj, jsid id, jsval * vp)
+{
+ int cook_l;
+ char *cook = initString(&cook_l);
+ const char *url = cw->fileName;
+ eb_bool secure = eb_false;
+ const char *proto;
+ char *s;
+
+ if(url) {
+ proto = getProtURL(url);
+ if(proto && stringEqualCI(proto, "https"))
+ secure = eb_true;
+ sendCookies(&cook, &cook_l, url, secure);
+ if(memEqualCI(cook, "cookie: ", 8)) { /* should often happen */
+ strmove(cook, cook + 8);
+ }
+ if(s = strstr(cook, "\r\n"))
+ *s = 0;
+ }
+
+ *vp = STRING_TO_JSVAL(our_JS_NewStringCopyZ(jcx, cook));
+ nzFree(cook);
+ return JS_TRUE;
+} /* getter_cookie */
+
+static JSBool
+setter_cookie(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *host = getHostURL(cw->fileName);
+ if(!host) {
+ JS_ReportError(jcx, "cannot set cookie, ill-defined domain");
+ } else {
+ const char *s = stringize(*vp);
+ if(!receiveCookie(cw->fileName, s))
+ JS_ReportError(jcx, "unable to set cookie %s", s);
+ }
+ return JS_TRUE;
+} /* setter_cookie */
+
+static JSBool
+setter_domain(JSContext * cx, JSObject * obj, jsid id, JSBool strict,
+ jsval * vp)
+{
+ const char *hostname = getHostURL(cw->fileName);
+ const char *dom = 0;
+ if(!hostname)
+ goto out; /* local file, don't care */
+ dom = stringize(*vp);
+ if(dom && strlen(dom) && domainSecurityCheck(hostname, dom))
+ goto out;
+ if(!dom)
+ dom = EMPTYSTRING;
+ JS_ReportError(jcx,
+ "document.domain is being set to an insecure string <%s>", dom);
+ out:
+ return JS_TRUE;
+} /* setter_domain */
+
+
+/*********************************************************************
+Convenient set property routines that can be invoked from edbrowse,
+requiring no knowledge of smjs.
+*********************************************************************/
+
+static JSBool(*my_getter) (JSContext *, JSObject *, jsid, jsval *);
+static JSBool(*my_setter) (JSContext *, JSObject *, jsid, JSBool, jsval *);
+
+void
+establish_property_string(void *jv, const char *name, const char *value,
+ eb_bool readonly)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
+ jsval v;
+ if(readonly)
+ attr |= JSPROP_READONLY;
+ my_getter = NULL;
+ my_setter = NULL;
+ if(stringEqual(name, "value"))
+ my_setter = setter_value;
+ if(stringEqual(name, "domain"))
+ my_setter = setter_domain;
+ if(stringEqual(name, "cookie")) {
+ my_getter = getter_cookie;
+ my_setter = setter_cookie;
+ }
+ if(value && *value)
+ v = STRING_TO_JSVAL(our_JS_NewStringCopyZ(jcx, value));
+ else {
+ v = JS_GetEmptyStringValue(jcx);
+ }
+ JS_DefineProperty(jcx, obj, name, v, my_getter, my_setter, attr);
+} /* establish_property_string */
+
+void
+establish_property_number(void *jv, const char *name, int value,
+ eb_bool readonly)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
+ if(readonly)
+ attr |= JSPROP_READONLY;
+ my_setter = NULL;
+ if(stringEqual(name, "selectedIndex"))
+ my_setter = setter_selidx;
+ JS_DefineProperty(jcx, obj, name,
+ INT_TO_JSVAL(value), NULL, my_setter, attr);
+} /* establish_property_number */
+
+void
+establish_property_bool(void *jv, const char *name, eb_bool value, eb_bool readonly)
+{
+ jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
+ if(readonly)
+ attr |= JSPROP_READONLY;
+ JSObject *obj = (JSObject *) jv;
+ my_setter = 0;
+ if(stringEqual(name, "checked"))
+ my_setter = setter_checked;
+ if(stringEqual(name, "selected"))
+ my_setter = setter_selected;
+ JS_DefineProperty(jcx, obj, name,
+ (value ? JSVAL_TRUE : JSVAL_FALSE), NULL, my_setter, attr);
+} /* establish_property_bool */
+
+void *
+establish_property_array(void *jv, const char *name)
+{
+ JSObject *obj = (JSObject *) jv;
+ JSObject *a = JS_NewArrayObject(jcx, 0, NULL);
+ establish_property_object(obj, name, a);
+ return a;
+} /* establish_property_array */
+
+void
+establish_property_object(void *parent, const char *name, void *child)
+{
+ JS_DefineProperty(jcx, (JSObject *) parent, name,
+ OBJECT_TO_JSVAL(((JSObject *) child)), 0, 0, PROP_FIXED);
+} /* establish_property_object */
+
+void
+establish_property_url(void *jv, const char *name,
+ const char *url, eb_bool readonly)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsuint attr = JSPROP_ENUMERATE | JSPROP_PERMANENT;
+ if(readonly)
+ attr |= JSPROP_READONLY;
+
+/* window.location, and document.location, has a special setter */
+ my_setter = 0;
+ if(stringEqual(name, "location"))
+ my_setter = setter_loc;
+ uo = JS_NewObject(jcx, &url_class, NULL, obj);
+ JS_DefineProperty(jcx, obj, name,
+ OBJECT_TO_JSVAL(uo), NULL, my_setter, attr);
+ if(!url)
+ url = EMPTYSTRING;
+ url_initialize(url, readonly, eb_false);
+ if(my_setter == setter_loc) {
+ if(obj == (JSObject *) jwin)
+ jwloc = uo;
+ else
+ jdloc = uo;
+ JS_DefineFunction(jcx, uo, "reload", loc_reload, 0, PROP_FIXED);
+ JS_DefineFunction(jcx, uo, "replace", loc_replace, 1, PROP_FIXED);
+ } /* location object */
+} /* establish_property_url */
+
+void
+set_property_string(void *jv, const char *name, const char *value)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsval vv;
+ setter_suspend = eb_true;
+ vv = ((value && *value) ? STRING_TO_JSVAL(our_JS_NewStringCopyZ(jcx, value))
+ : JS_GetEmptyStringValue(jcx));
+ JS_SetProperty(jcx, obj, name, &vv);
+ setter_suspend = eb_false;
+} /* set_property_string */
+
+void
+set_property_number(void *jv, const char *name, int value)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsval vv;
+ setter_suspend = eb_true;
+ vv = INT_TO_JSVAL(value);
+ JS_SetProperty(jcx, obj, name, &vv);
+ setter_suspend = eb_false;
+} /* set_property_number */
+
+void
+set_property_bool(void *jv, const char *name, int value)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsval vv;
+ setter_suspend = eb_true;
+ vv = (value ? JSVAL_TRUE : JSVAL_FALSE);
+ JS_SetProperty(jcx, obj, name, &vv);
+ setter_suspend = eb_false;
+} /* set_property_bool */
+
+/* These get routines assume the property exists, and of the right type. */
+char *
+get_property_url(void *jv, eb_bool doaction)
+{
+ JSObject *obj = (JSObject *) jv;
+ JSObject *lo; /* location object */
+ jsval v;
+ const char *s;
+ char *out_str = NULL;
+ int out_str_l;
+ JSBool found = eb_false;
+ if(!obj)
+ return 0;
+ if(!doaction) {
+ JS_HasProperty(jcx, obj, "href", &found);
+ if(found)
+ JS_GetProperty(jcx, obj, "href", &v);
+ if(!found) {
+ JS_HasProperty(jcx, obj, "src", &found);
+ if(found)
+ JS_GetProperty(jcx, obj, "src", &v);
+ }
+ } else {
+ JS_HasProperty(jcx, obj, "action", &found);
+ if(found)
+ JS_GetProperty(jcx, obj, "action", &v);
+ }
+ if(!found)
+ return 0;
+ if(!JSVAL_IS_STRING(v)) {
+ if(!JSVAL_IS_OBJECT(v)) {
+ badobj:
+ JS_ReportError(jcx,
+ "url object is assigned something that I don't understand; I may not be able to fetch the next web page.");
+ return 0;
+ }
+ lo = JSVAL_TO_OBJECT(v);
+ JS_HasProperty(jcx, lo, "actioncrash", &found);
+ if(found)
+ return 0;
+ if(!JS_InstanceOf(jcx, lo, &url_class, emptyArgs))
+ goto badobj;
+ JS_GetProperty(jcx, lo, "href", &v);
+ }
+ s = stringize(v);
+ if(!JS_CStringsAreUTF8()) {
+ out_str = cloneString(s);
+ } else {
+ if(cons_utf8) {
+ out_str = cloneString(s);
+ } else {
+ utf2iso(s, strlen(s), &out_str, &out_str_l);
+ }
+ }
+ return out_str;
+} /* get_property_url */
+
+char *
+get_property_string(void *jv, const char *name)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsval v;
+ const char *s = NULL;
+ char *out_str = NULL;
+ char *converted;
+ int converted_l;
+ if(!obj)
+ return 0;
+ JS_GetProperty(jcx, obj, name, &v);
+ s = stringize(v);
+ if(!JS_CStringsAreUTF8()) {
+ out_str = cloneString(s);
+ } else {
+ if(cons_utf8) {
+ out_str = cloneString(s);
+ } else {
+ utf2iso(s, strlen(s), &converted, &converted_l);
+ out_str = converted;
+ }
+ }
+ return out_str;
+} /* get_property_string */
+
+eb_bool
+get_property_bool(void *jv, const char *name)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsval v;
+ if(!obj)
+ return eb_false;
+ JS_GetProperty(jcx, obj, name, &v);
+ return JSVAL_TO_BOOLEAN(v);
+} /* get_property_bool */
+
+char *
+get_property_option(void *jv)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsval v;
+ JSObject *oa; /* option array */
+ JSObject *oo; /* option object */
+ int n;
+
+ if(!obj)
+ return 0;
+ JS_GetProperty(jcx, obj, "selectedIndex", &v);
+ n = JSVAL_TO_INT(v);
+ if(n < 0)
+ return 0;
+ JS_GetProperty(jcx, obj, "options", &v);
+ oa = JSVAL_TO_OBJECT(v);
+ JS_GetElement(jcx, oa, n, &v);
+ oo = JSVAL_TO_OBJECT(v);
+ return get_property_string(oo, "value");
+} /* get_property_option */
+
+
+/*********************************************************************
+Manage the array of options under an html select.
+This will explode into a lot of code, if we ever implement
+dynamic option lists under js control.
+*********************************************************************/
+
+static JSClass option_class = {
+ "Option",
+ JSCLASS_HAS_PRIVATE,
+ JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
+ JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
+};
+void *
+establish_js_option(void *ev, int idx)
+{
+ JSObject *so = (JSObject *) ev; /* select object */
+ jsval vv;
+ JSObject *oa; /* option array */
+ JSObject *oo; /* option object */
+ JS_GetProperty(jcx, so, "options", &vv);
+ oa = JSVAL_TO_OBJECT(vv);
+ oo = JS_NewObject(jcx, &option_class, NULL, so);
+ vv = OBJECT_TO_JSVAL(oo);
+ JS_DefineElement(jcx, oa, idx, vv, NULL, NULL, JSPROP_ENUMERATE);
+/* option.form = select.form */
+ JS_GetProperty(jcx, so, "form", &vv);
+ JS_SetProperty(jcx, oo, "form", &vv);
+ return oo;
+} /* establish_js_option */
+
+
+/*********************************************************************
+Compile and call event handlers.
+*********************************************************************/
+
+eb_bool
+handlerGo(void *obj, const char *name)
+{
+ jsval rval;
+ eb_bool rc;
+ JSBool found;
+ JS_HasProperty(jcx, (JSObject *) obj, name, &found);
+ if(!found)
+ return eb_false;
+ rc = JS_CallFunctionName(jcx, (JSObject *) obj, name, 0, emptyArgs, &rval);
+ if(rc && JSVAL_IS_BOOLEAN(rval))
+ rc = JSVAL_TO_BOOLEAN(rval);
+ JS_GC(jcx);
+ return rc;
+} /* handlerGo */
+
+void
+handlerSet(void *ev, const char *name, const char *code)
+{
+ JSObject *obj = (JSObject *) ev;
+ char *newcode;
+ JSBool found;
+ if(!obj)
+ return;
+ newcode = (char *) allocMem(strlen(code) + 60);
+ strcpy(newcode, "with(document) { ");
+ JS_HasProperty(jcx, obj, "form", &found);
+ if(found)
+ strcat(newcode, "with(this.form) { ");
+ strcat(newcode, code);
+ if(found)
+ strcat(newcode, " }");
+ strcat(newcode, " }");
+ JS_CompileFunction(jcx, obj, name, 0, emptyParms, /* no named parameters */
+ newcode, strlen(newcode), name, 1);
+ nzFree(newcode);
+} /* handlerSet */
+
+void
+link_onunload_onclick(void *jv)
+{
+ JSObject *obj = (JSObject *) jv;
+ jsval v;
+ JS_GetProperty(jcx, obj, "onunload", &v);
+ JS_DefineProperty(jcx, obj, "onclick", v, 0, 0, PROP_FIXED);
+} /* link_onunload_onclick */
+
+eb_bool
+handlerPresent(void *ev, const char *name)
+{
+ JSObject *obj = (JSObject *) ev;
+ JSBool found = JS_FALSE;
+ if(!obj)
+ return eb_false;
+ JS_HasProperty(jcx, obj, name, &found);
+ return found;
+} /* handlerPresent */
--
1.8.5.2.297.g3e57c29
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2013-12-24 18:58 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-24 18:57 [Edbrowse-dev] [PATCH 1/2] Initial version of jsloc.cpp (built against mozjs 1.85) also rename objClass to obj_class in jsdom.cpp Adam Thompson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).