summaryrefslogtreecommitdiff
path: root/javascript/duktape
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-10-12 17:40:35 +0100
committerVincent Sanders <vince@kyllikki.org>2015-10-12 17:40:35 +0100
commitce321410577f384e19042ea20b30ed6cbb00eda2 (patch)
treed1efc9a5d2fd4da26e16a34b18d0a53055a7e77c /javascript/duktape
parent3877d4ad03134c727624b85e830539b3fe15dbdf (diff)
downloadnetsurf-ce321410577f384e19042ea20b30ed6cbb00eda2.tar.gz
netsurf-ce321410577f384e19042ea20b30ed6cbb00eda2.tar.bz2
Split up javascript engine makefiles
by splitting javascript engine specific makefiles and source up we avoid having to consider old JSAPI or none code while working on duktape.
Diffstat (limited to 'javascript/duktape')
-rw-r--r--javascript/duktape/Makefile37
-rw-r--r--javascript/duktape/dukky.c389
-rw-r--r--javascript/duktape/dukky.h32
-rw-r--r--javascript/duktape/netsurf.bnd2
4 files changed, 459 insertions, 1 deletions
diff --git a/javascript/duktape/Makefile b/javascript/duktape/Makefile
new file mode 100644
index 000000000..6f7019a7f
--- /dev/null
+++ b/javascript/duktape/Makefile
@@ -0,0 +1,37 @@
+#
+# NetSurf javascript source file inclusion
+#
+# Included by javascript/Makefile
+#
+
+javascript/dukky.c: $(OBJROOT)/duktape/binding.h
+
+BINDINGS := $(wildcard javascript/duktape/*.bnd)
+
+$(OBJROOT)/duktape/binding.h $(OBJROOT)/duktape/Makefile: javascript/duktape/netsurf.bnd $(BINDINGS)
+ $(Q)mkdir -p $(OBJROOT)/duktape
+ $(VQ)echo " GENBIND: $<"
+ $(Q)nsgenbind -D -g -I javascript/WebIDL $< $(OBJROOT)/duktape
+ $(VQ)echo " GENBIND: completed"
+
+# create unimplemented report for doxygen
+Docs/UnimplementedJavascript.txt: javascript/duktape/netsurf.bnd $(BINDINGS)
+ $(Q)mkdir -p $(OBJROOT)/duktape
+ $(VQ)echo "/** \page unimplemented Unimplemented javascript bindings" > $@
+ $(VQ)echo "This is a list of all the binding methods, getters and setters without an implementation in a binding." >> $@
+ $(VQ)echo "" >> $@
+ $(VQ)echo " GENBIND: $<"
+ $(Q)nsgenbind -Wunimplemented -I javascript/WebIDL $< $(OBJROOT)/duktape 2>&1 >/dev/null | grep "Unimplemented" | cut -d' ' -f4- | sort -k 2 | awk '{print $$0"\\n" }' >> $@
+ $(VQ)echo "*/" >> $@
+
+ifeq ($(filter $(MAKECMDGOALS),clean test coverage),)
+-include $(OBJROOT)/duktape/Makefile
+endif
+
+S_JAVASCRIPT_BINDING:=$(addprefix $(OBJROOT)/duktape/,$(NSGENBIND_SOURCES))
+
+$(S_JAVASCRIPT_BINDING): $(BINDINGS)
+
+S_JAVASCRIPT += content.c duktape/dukky.c duktape/duktape.c
+
+CFLAGS += -DDUK_OPT_HAVE_CUSTOM_H
diff --git a/javascript/duktape/dukky.c b/javascript/duktape/dukky.c
new file mode 100644
index 000000000..9e3608037
--- /dev/null
+++ b/javascript/duktape/dukky.c
@@ -0,0 +1,389 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ * Copyright 2015 All of us.
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Duktapeish implementation of javascript engine functions.
+ */
+
+#include "content/content.h"
+
+#include "utils/nsoption.h"
+#include "utils/log.h"
+#include "utils/corestrings.h"
+
+#include "javascript/js.h"
+#include "javascript/content.h"
+
+#include "duktape/binding.h"
+
+#include "duktape.h"
+#include "dukky.h"
+
+#include <dom/dom.h>
+
+static duk_ret_t dukky_populate_object(duk_context *ctx)
+{
+ /* ... obj args protoname nargs */
+ int nargs = duk_get_int(ctx, -1);
+ duk_pop(ctx);
+ /* ... obj args protoname */
+ duk_get_global_string(ctx, PROTO_MAGIC);
+ /* .. obj args protoname prototab */
+ duk_insert(ctx, -2);
+ /* ... obj args prototab protoname */
+ duk_get_prop(ctx, -2);
+ /* ... obj args prototab {proto/undefined} */
+ if (duk_is_undefined(ctx, -1)) {
+ LOG("RuhRoh, couldn't find a prototype, HTMLUnknownElement it is");
+ duk_pop(ctx);
+ duk_push_string(ctx, PROTO_NAME(HTMLUNKNOWNELEMENT));
+ duk_get_prop(ctx, -2);
+ }
+ /* ... obj args prototab proto */
+ duk_dup(ctx, -1);
+ /* ... obj args prototab proto proto */
+ duk_set_prototype(ctx, -(nargs+4));
+ /* ... obj[proto] args prototab proto */
+ duk_get_prop_string(ctx, -1, INIT_MAGIC);
+ /* ... obj[proto] args prototab proto initfn */
+ duk_insert(ctx, -(nargs+4));
+ /* ... initfn obj[proto] args prototab proto */
+ duk_pop_2(ctx);
+ /* ... initfn obj[proto] args */
+ LOG("Call the init function");
+ duk_call(ctx, nargs + 1);
+ return 1; /* The object */
+}
+
+duk_ret_t dukky_create_object(duk_context *ctx, const char *name, int args)
+{
+ duk_ret_t ret;
+ LOG("name=%s nargs=%d", name+2, args);
+ /* ... args */
+ duk_push_object(ctx);
+ /* ... args obj */
+ duk_insert(ctx, -(args+1));
+ /* ... obj args */
+ duk_push_string(ctx, name);
+ /* ... obj args name */
+ duk_push_int(ctx, args);
+ /* ... obj args name nargs */
+ if ((ret = duk_safe_call(ctx, dukky_populate_object, args + 3, 1))
+ != DUK_EXEC_SUCCESS)
+ return ret;
+ LOG("created");
+ return DUK_EXEC_SUCCESS;
+}
+
+
+
+duk_bool_t
+dukky_push_node_stacked(duk_context *ctx)
+{
+ int top_at_fail = duk_get_top(ctx) - 2;
+ /* ... nodeptr klass */
+ duk_get_global_string(ctx, NODE_MAGIC);
+ /* ... nodeptr klass nodes */
+ duk_dup(ctx, -3);
+ /* ... nodeptr klass nodes nodeptr */
+ duk_get_prop(ctx, -2);
+ /* ... nodeptr klass nodes node/undefined */
+ if (duk_is_undefined(ctx, -1)) {
+ /* ... nodeptr klass nodes undefined */
+ duk_pop(ctx);
+ /* ... nodeptr klass nodes */
+ duk_push_object(ctx);
+ /* ... nodeptr klass nodes obj */
+ duk_dup(ctx, -4);
+ /* ... nodeptr klass nodes obj nodeptr */
+ duk_dup(ctx, -4);
+ /* ... nodeptr klass nodes obj nodeptr klass */
+ duk_push_int(ctx, 1);
+ /* ... nodeptr klass nodes obj nodeptr klass 1 */
+ if (duk_safe_call(ctx, dukky_populate_object, 4, 1)
+ != DUK_EXEC_SUCCESS) {
+ duk_set_top(ctx, top_at_fail);
+ LOG("Boo and also hiss");
+ return false;
+ }
+ /* ... nodeptr klass nodes node */
+ duk_dup(ctx, -4);
+ /* ... nodeptr klass nodes node nodeptr */
+ duk_dup(ctx, -2);
+ /* ... nodeptr klass nodes node nodeptr node */
+ duk_put_prop(ctx, -4);
+ /* ... nodeptr klass nodes node */
+ }
+ /* ... nodeptr klass nodes node */
+ duk_insert(ctx, -4);
+ /* ... node nodeptr klass nodes */
+ duk_pop_3(ctx);
+ /* ... node */
+ return true;
+}
+
+static void
+dukky_push_node_klass(duk_context *ctx, struct dom_node *node)
+{
+ dom_node_type nodetype;
+ dom_exception err;
+
+ err = dom_node_get_node_type(node, &nodetype);
+ if (err != DOM_NO_ERR) {
+ /* Oh bum, just node then */
+ duk_push_string(ctx, PROTO_NAME(NODE));
+ return;
+ }
+
+ switch(nodetype) {
+ case DOM_ELEMENT_NODE: {
+ dom_string *namespace, *tag;
+ err = dom_node_get_namespace(node, &namespace);
+ if (err != DOM_NO_ERR) {
+ /* Feck it, element */
+ LOG("dom_node_get_namespace() failed");
+ duk_push_string(ctx, PROTO_NAME(ELEMENT));
+ break;
+ }
+ if (namespace == NULL) {
+ /* No namespace, -> element */
+ LOG("no namespace");
+ duk_push_string(ctx, PROTO_NAME(ELEMENT));
+ break;
+ }
+
+ if (dom_string_isequal(namespace, corestring_dom_html_namespace) == false) {
+ /* definitely not an HTML element of some kind */
+ duk_push_string(ctx, PROTO_NAME(ELEMENT));
+ dom_string_unref(namespace);
+ break;
+ }
+ dom_string_unref(namespace);
+
+ err = dom_node_get_node_name(node, &tag);
+ if (err != DOM_NO_ERR) {
+ duk_push_string(ctx, PROTO_NAME(HTMLUNKNOWNELEMENT));
+ break;
+ }
+
+ duk_push_string(ctx, PROTO_NAME(HTML));
+ duk_push_lstring(ctx, dom_string_data(tag), dom_string_length(tag));
+ dom_string_unref(tag);
+ duk_push_string(ctx, "ELEMENT");
+ duk_concat(ctx, 3);
+
+ break;
+ }
+ case DOM_TEXT_NODE:
+ duk_push_string(ctx, PROTO_NAME(TEXT));
+ break;
+ case DOM_COMMENT_NODE:
+ duk_push_string(ctx, PROTO_NAME(COMMENT));
+ break;
+ case DOM_DOCUMENT_NODE:
+ duk_push_string(ctx, PROTO_NAME(DOCUMENT));
+ break;
+ case DOM_ATTRIBUTE_NODE:
+ case DOM_PROCESSING_INSTRUCTION_NODE:
+ case DOM_DOCUMENT_TYPE_NODE:
+ case DOM_DOCUMENT_FRAGMENT_NODE:
+ case DOM_NOTATION_NODE:
+ case DOM_ENTITY_REFERENCE_NODE:
+ case DOM_ENTITY_NODE:
+ case DOM_CDATA_SECTION_NODE:
+ default:
+ /* Oh bum, just node then */
+ duk_push_string(ctx, PROTO_NAME(NODE));
+ }
+}
+
+duk_bool_t
+dukky_push_node(duk_context *ctx, struct dom_node *node)
+{
+ LOG("Pushing node %p", node);
+ /* First check if we can find the node */
+ /* ... */
+ duk_get_global_string(ctx, NODE_MAGIC);
+ /* ... nodes */
+ duk_push_pointer(ctx, node);
+ /* ... nodes nodeptr */
+ duk_get_prop(ctx, -2);
+ /* ... nodes node/undefined */
+ if (!duk_is_undefined(ctx, -1)) {
+ /* ... nodes node */
+ duk_insert(ctx, -2);
+ /* ... node nodes */
+ duk_pop(ctx);
+ /* ... node */
+ LOG("Found it memoised");
+ return true;
+ }
+ /* ... nodes undefined */
+ duk_pop_2(ctx);
+ /* ... */
+ /* We couldn't, so now we determine the node type and then
+ * we ask for it to be created
+ */
+ duk_push_pointer(ctx, node);
+ /* ... nodeptr */
+ dukky_push_node_klass(ctx, node);
+ /* ... nodeptr klass */
+ return dukky_push_node_stacked(ctx);
+}
+
+static duk_ret_t
+dukky_bad_constructor(duk_context *ctx)
+{
+ duk_error(ctx, DUK_ERR_ERROR, "Bad constructor");
+ return 0;
+}
+
+void
+dukky_inject_not_ctr(duk_context *ctx, int idx, const char *name)
+{
+ /* ... p[idx] ... proto */
+ duk_push_c_function(ctx, dukky_bad_constructor, 0);
+ /* ... p[idx] ... proto cons */
+ duk_insert(ctx, -2);
+ /* ... p[idx] ... cons proto */
+ duk_put_prop_string(ctx, -2, "prototype");
+ /* ... p[idx] ... cons[proto] */
+ duk_put_prop_string(ctx, idx, name);
+ /* ... p ... */
+ return;
+}
+
+/**************************************** js.h ******************************/
+struct jscontext {
+ duk_context *ctx;
+ duk_context *thread;
+};
+
+#define CTX (ctx->thread)
+
+void js_initialise(void)
+{
+ /** TODO: Forces JS on for our testing, needs changing before a release
+ * lest we incur the wrath of others.
+ */
+ nsoption_set_bool(enable_javascript, true);
+ javascript_init();
+}
+
+void js_finalise(void)
+{
+ /* NADA for now */
+}
+
+#define DUKKY_NEW_PROTOTYPE(klass, uklass, klass_name) \
+ dukky_create_prototype(ctx, dukky_##klass##___proto, PROTO_NAME(uklass), klass_name)
+
+nserror js_newcontext(int timeout, jscallback *cb, void *cbctx,
+ jscontext **jsctx)
+{
+ duk_context *ctx;
+ jscontext *ret = calloc(1, sizeof(*ret));
+ *jsctx = NULL;
+ LOG("Creating new duktape javascript context");
+ if (ret == NULL) return NSERROR_NOMEM;
+ ctx = ret->ctx = duk_create_heap_default();
+ if (ret->ctx == NULL) { free(ret); return NSERROR_NOMEM; }
+ /* Create the prototype stuffs */
+ duk_push_global_object(ctx);
+ duk_push_boolean(ctx, true);
+ duk_put_prop_string(ctx, -2, "protos");
+ duk_put_global_string(ctx, PROTO_MAGIC);
+ /* Create prototypes here */
+ dukky_create_prototypes(ctx);
+
+ *jsctx = ret;
+ return NSERROR_OK;
+}
+
+void js_destroycontext(jscontext *ctx)
+{
+ LOG("Destroying duktape javascript context");
+ duk_destroy_heap(ctx->ctx);
+ free(ctx);
+}
+
+jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv)
+{
+ assert(ctx != NULL);
+ /* Pop any active thread off */
+ LOG("Yay, new compartment, win_priv=%p, doc_priv=%p", win_priv, doc_priv);
+ duk_set_top(ctx->ctx, 0);
+ duk_push_thread(ctx->ctx);
+ ctx->thread = duk_require_context(ctx->ctx, -1);
+ duk_push_int(CTX, 0);
+ duk_push_int(CTX, 1);
+ duk_push_int(CTX, 2);
+ /* Manufacture a Window object */
+ /* win_priv is a browser_window, doc_priv is an html content struct */
+ duk_push_pointer(CTX, win_priv);
+ duk_push_pointer(CTX, doc_priv);
+ dukky_create_object(CTX, PROTO_NAME(WINDOW), 2);
+ duk_push_global_object(CTX);
+ duk_put_prop_string(CTX, -2, PROTO_MAGIC);
+ duk_set_global_object(CTX);
+
+ /* Now we need to prepare our node mapping table */
+ duk_push_object(CTX);
+ duk_put_global_string(CTX, NODE_MAGIC);
+
+ return (jsobject *)ctx;
+}
+
+static duk_ret_t eval_top_string(duk_context *ctx)
+{
+ duk_eval(ctx);
+ return 0;
+}
+
+bool js_exec(jscontext *ctx, const char *txt, size_t txtlen)
+{
+ assert(ctx);
+ if (txt == NULL || txtlen == 0) return false;
+ duk_set_top(CTX, 0);
+ duk_push_lstring(CTX, txt, txtlen);
+
+ if (duk_safe_call(CTX, eval_top_string, 1, 1) == DUK_EXEC_ERROR) {
+ duk_get_prop_string(CTX, 0, "name");
+ duk_get_prop_string(CTX, 0, "message");
+ duk_get_prop_string(CTX, 0, "fileName");
+ duk_get_prop_string(CTX, 0, "lineNumber");
+ duk_get_prop_string(CTX, 0, "stack");
+ LOG("Uncaught error in JS: %s: %s", duk_safe_to_string(CTX, 1),
+ duk_safe_to_string(CTX, 2));
+ LOG(" was at: %s line %s", duk_safe_to_string(CTX, 3),
+ duk_safe_to_string(CTX, 4));
+ LOG(" Stack trace: %s", duk_safe_to_string(CTX, 5));
+ return false;
+ }
+ if (duk_get_top(CTX) == 0) duk_push_boolean(CTX, false);
+ LOG("Returning %s", duk_get_boolean(CTX, 0) ? "true" : "false");
+ return duk_get_boolean(CTX, 0);
+}
+
+bool js_fire_event(jscontext *ctx, const char *type, struct dom_document *doc, struct dom_node *target)
+{
+ /* La La La */
+ LOG("Oh dear, an event: %s", type);
+ return true;
+}
diff --git a/javascript/duktape/dukky.h b/javascript/duktape/dukky.h
new file mode 100644
index 000000000..abe21ba35
--- /dev/null
+++ b/javascript/duktape/dukky.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2012 Vincent Sanders <vince@netsurf-browser.org>
+ * Copyright 2015 All of us.
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Duktapeish implementation of javascript engine functions, prototypes.
+ */
+
+#ifndef DUKKY_H
+#define DUKKY_H
+
+duk_ret_t dukky_create_object(duk_context *ctx, const char *name, int args);
+duk_bool_t dukky_push_node_stacked(duk_context *ctx);
+duk_bool_t dukky_push_node(duk_context *ctx, struct dom_node *node);
+void dukky_inject_not_ctr(duk_context *ctx, int idx, const char *name);
+
+#endif
diff --git a/javascript/duktape/netsurf.bnd b/javascript/duktape/netsurf.bnd
index 12292454c..c60b66752 100644
--- a/javascript/duktape/netsurf.bnd
+++ b/javascript/duktape/netsurf.bnd
@@ -47,7 +47,7 @@ struct dom_html_br_element;
%};
prologue %{
-#include "javascript/dukky.h"
+#include "javascript/duktape/dukky.h"
%};
};