summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--content/handlers/javascript/duktape/Makefile12
-rw-r--r--content/handlers/javascript/duktape/dukky.c20
-rw-r--r--content/handlers/javascript/duktape/generics.js2
-rw-r--r--content/handlers/javascript/duktape/polyfill.js85
4 files changed, 117 insertions, 2 deletions
diff --git a/content/handlers/javascript/duktape/Makefile b/content/handlers/javascript/duktape/Makefile
index 7c9e60a8b..d15b71291 100644
--- a/content/handlers/javascript/duktape/Makefile
+++ b/content/handlers/javascript/duktape/Makefile
@@ -4,7 +4,10 @@
# Included by javascript/Makefile
#
-content/handlers/javascript/duktape/dukky.c: $(OBJROOT)/duktape/binding.h $(OBJROOT)/duktape/generics.js.inc
+content/handlers/javascript/duktape/dukky.c: \
+ $(OBJROOT)/duktape/binding.h \
+ $(OBJROOT)/duktape/generics.js.inc \
+ $(OBJROOT)/duktape/polyfill.js.inc
BINDINGS := $(wildcard content/handlers/javascript/duktape/*.bnd)
@@ -15,6 +18,13 @@ $(OBJROOT)/duktape/generics.js.inc: content/handlers/javascript/duktape/generics
$(Q)xxd -i $< $@.tmp
$(Q)sed -e 's/content_handlers_javascript_duktape_generics_js/generics_js/' $@.tmp > $@
+# Generator for the C include representing the polyfill.js
+$(OBJROOT)/duktape/polyfill.js.inc: content/handlers/javascript/duktape/polyfill.js
+ $(Q)$(MKDIR) -p $(OBJROOT)/duktape
+ $(VQ)echo " XXD: $<"
+ $(Q)xxd -i $< $@.tmp
+ $(Q)sed -e 's/content_handlers_javascript_duktape_polyfill_js/polyfill_js/' $@.tmp > $@
+
# ensure genbind generates debugging files
GBFLAGS+=-D
diff --git a/content/handlers/javascript/duktape/dukky.c b/content/handlers/javascript/duktape/dukky.c
index 491c5c276..cd3549e93 100644
--- a/content/handlers/javascript/duktape/dukky.c
+++ b/content/handlers/javascript/duktape/dukky.c
@@ -39,6 +39,7 @@
#include "duktape/binding.h"
#include "duktape/generics.js.inc"
+#include "duktape/polyfill.js.inc"
#include "duktape.h"
#include "dukky.h"
@@ -681,6 +682,25 @@ jsobject *js_newcompartment(jscontext *ctx, void *win_priv, void *doc_priv)
duk_push_object(CTX);
duk_put_global_string(CTX, EVENT_MAGIC);
+ /* Now load the polyfills */
+ /* ... */
+ duk_push_string(CTX, "polyfill.js");
+ /* ..., polyfill.js */
+ if (duk_pcompile_lstring_filename(CTX, DUK_COMPILE_EVAL,
+ (const char *)polyfill_js, polyfill_js_len) != 0) {
+ NSLOG(dukky, CRITICAL, "%s", duk_safe_to_string(CTX, -1));
+ NSLOG(dukky, CRITICAL, "Unable to compile polyfill.js, compartment aborted");
+ return NULL;
+ }
+ /* ..., (generics.js) */
+ if (dukky_pcall(CTX, 0, true) != 0) {
+ NSLOG(dukky, CRITICAL, "Unable to run polyfill.js, compartment aborted");
+ return NULL;
+ }
+ /* ..., result */
+ duk_pop(CTX);
+ /* ... */
+
/* Now load the NetSurf table in */
/* ... */
duk_push_string(CTX, "generics.js");
diff --git a/content/handlers/javascript/duktape/generics.js b/content/handlers/javascript/duktape/generics.js
index 6850c9b7d..29beffc2c 100644
--- a/content/handlers/javascript/duktape/generics.js
+++ b/content/handlers/javascript/duktape/generics.js
@@ -44,7 +44,7 @@ var NetSurf = {
const offset = target.search("%");
- if (offset == -1 || offset >= target.length) {
+ if (offset == -1 || offset >= (target.length - 1)) {
// We've a string, but the % either doesn't exist or is
// at the end of it, so give up
return Array.from(arguments);
diff --git a/content/handlers/javascript/duktape/polyfill.js b/content/handlers/javascript/duktape/polyfill.js
new file mode 100644
index 000000000..7fa46111f
--- /dev/null
+++ b/content/handlers/javascript/duktape/polyfill.js
@@ -0,0 +1,85 @@
+/* Polyfiller for Duktape for NetSurf
+ *
+ * This JavaScript will be loaded into compartments before the generics
+ *
+ * We only care for the side-effects of this, be careful.
+ */
+
+// Production steps of ECMA-262, Edition 6, 22.1.2.1
+if (!Array.from) {
+ Array.from = (function () {
+ var toStr = Object.prototype.toString;
+ var isCallable = function (fn) {
+ return typeof fn === 'function' || toStr.call(fn) === '[object Function]';
+ };
+ var toInteger = function (value) {
+ var number = Number(value);
+ if (isNaN(number)) { return 0; }
+ if (number === 0 || !isFinite(number)) { return number; }
+ return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));
+ };
+ var maxSafeInteger = Math.pow(2, 53) - 1;
+ var toLength = function (value) {
+ var len = toInteger(value);
+ return Math.min(Math.max(len, 0), maxSafeInteger);
+ };
+
+ // The length property of the from method is 1.
+ return function from(arrayLike/*, mapFn, thisArg */) {
+ // 1. Let C be the this value.
+ var C = this;
+
+ // 2. Let items be ToObject(arrayLike).
+ var items = Object(arrayLike);
+
+ // 3. ReturnIfAbrupt(items).
+ if (arrayLike == null) {
+ throw new TypeError('Array.from requires an array-like object - not null or undefined');
+ }
+
+ // 4. If mapfn is undefined, then let mapping be false.
+ var mapFn = arguments.length > 1 ? arguments[1] : void undefined;
+ var T;
+ if (typeof mapFn !== 'undefined') {
+ // 5. else
+ // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.
+ if (!isCallable(mapFn)) {
+ throw new TypeError('Array.from: when provided, the second argument must be a function');
+ }
+
+ // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.
+ if (arguments.length > 2) {
+ T = arguments[2];
+ }
+ }
+
+ // 10. Let lenValue be Get(items, "length").
+ // 11. Let len be ToLength(lenValue).
+ var len = toLength(items.length);
+
+ // 13. If IsConstructor(C) is true, then
+ // 13. a. Let A be the result of calling the [[Construct]] internal method
+ // of C with an argument list containing the single item len.
+ // 14. a. Else, Let A be ArrayCreate(len).
+ var A = isCallable(C) ? Object(new C(len)) : new Array(len);
+
+ // 16. Let k be 0.
+ var k = 0;
+ // 17. Repeat, while k < len… (also steps a - h)
+ var kValue;
+ while (k < len) {
+ kValue = items[k];
+ if (mapFn) {
+ A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);
+ } else {
+ A[k] = kValue;
+ }
+ k += 1;
+ }
+ // 18. Let putStatus be Put(A, "length", len, true).
+ A.length = len;
+ // 20. Return A.
+ return A;
+ };
+ }());
+}