diff --git a/Makefile b/Makefile index 4d24541..c83a25c 100755 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ DBG ?= 1 OPT ?= 0 INFO := +LD = $(CC) ifeq ($(DBG),1) CFLAGS += -g @@ -25,13 +26,13 @@ else endif ifeq ($(OPT),small) - CFLAGS += -Os - AR = ar + CFLAGS += -Oz -flto -fno-ident -fno-asynchronous-unwind-tables + LDFLAGS += -flto INFO := $(addsuffix _small,$(INFO)) else ifeq ($(OPT), 1) CFLAGS += -O2 -flto - AR = llvm-ar + LDFLAGS += -flto INFO := $(addsuffix _opt,$(INFO)) else CFLAGS += -O0 @@ -125,9 +126,9 @@ install: $(DISTDIR)/$(DIST) # @unzip $(DISTDIR)/$(DIST) -d $(DESTDIR) @$(UNZIP) -$(BIN)/$(NAME): $(BIN)/libengine.a $(BIN)/libquickjs.a +$(BIN)/$(NAME): $(BIN)/libengine.a $(BIN)/libquickjs.lto.a @echo Linking $(NAME) - $(CC) $^ $(LDFLAGS) $(LDLIBS) -o $@ + $(LD) $^ $(LDFLAGS) $(LDLIBS) -o $@ @echo Finished build $(DISTDIR)/$(DIST): $(BIN)/$(NAME) source/shaders/* $(SCRIPTS) assets/* @@ -141,7 +142,7 @@ $(DISTDIR)/$(DIST): $(BIN)/$(NAME) source/shaders/* $(SCRIPTS) assets/* $(BIN)/libengine.a: $(OBJS) @$(AR) r $@ $^ -$(BIN)/libquickjs.a: +$(BIN)/libquickjs.lto.a: make -C quickjs clean make -C quickjs libquickjs.a libquickjs.lto.a CC=$(CC) cp quickjs/libquickjs.* $(BIN) diff --git a/quickjs/Makefile b/quickjs/Makefile index a53c96f..7f80ba9 100644 --- a/quickjs/Makefile +++ b/quickjs/Makefile @@ -110,7 +110,7 @@ endif CFLAGS+=$(DEFINES) CFLAGS_DEBUG=$(CFLAGS) -O0 CFLAGS_SMALL=$(CFLAGS) -Os -CFLAGS_OPT=$(CFLAGS) -O2 +CFLAGS_OPT=$(CFLAGS) -Oz CFLAGS_NOLTO:=$(CFLAGS_OPT) LDFLAGS=-g ifdef CONFIG_LTO diff --git a/quickjs/examples/fib.c b/quickjs/examples/fib.c deleted file mode 100644 index c77b705..0000000 --- a/quickjs/examples/fib.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * QuickJS: Example of C module - * - * Copyright (c) 2017-2018 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "../quickjs.h" - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -static int fib(int n) -{ - if (n <= 0) - return 0; - else if (n == 1) - return 1; - else - return fib(n - 1) + fib(n - 2); -} - -static JSValue js_fib(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int n, res; - if (JS_ToInt32(ctx, &n, argv[0])) - return JS_EXCEPTION; - res = fib(n); - return JS_NewInt32(ctx, res); -} - -static const JSCFunctionListEntry js_fib_funcs[] = { - JS_CFUNC_DEF("fib", 1, js_fib ), -}; - -static int js_fib_init(JSContext *ctx, JSModuleDef *m) -{ - return JS_SetModuleExportList(ctx, m, js_fib_funcs, - countof(js_fib_funcs)); -} - -#ifdef JS_SHARED_LIBRARY -#define JS_INIT_MODULE js_init_module -#else -#define JS_INIT_MODULE js_init_module_fib -#endif - -JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) -{ - JSModuleDef *m; - m = JS_NewCModule(ctx, module_name, js_fib_init); - if (!m) - return NULL; - JS_AddModuleExportList(ctx, m, js_fib_funcs, countof(js_fib_funcs)); - return m; -} diff --git a/quickjs/examples/fib_module.js b/quickjs/examples/fib_module.js deleted file mode 100644 index 6a81071..0000000 --- a/quickjs/examples/fib_module.js +++ /dev/null @@ -1,10 +0,0 @@ -/* fib module */ -export function fib(n) -{ - if (n <= 0) - return 0; - else if (n == 1) - return 1; - else - return fib(n - 1) + fib(n - 2); -} diff --git a/quickjs/examples/hello.js b/quickjs/examples/hello.js deleted file mode 100644 index accefce..0000000 --- a/quickjs/examples/hello.js +++ /dev/null @@ -1 +0,0 @@ -console.log("Hello World"); diff --git a/quickjs/examples/hello_module.js b/quickjs/examples/hello_module.js deleted file mode 100644 index 463660f..0000000 --- a/quickjs/examples/hello_module.js +++ /dev/null @@ -1,6 +0,0 @@ -/* example of JS module */ - -import { fib } from "./fib_module.js"; - -console.log("Hello World"); -console.log("fib(10)=", fib(10)); diff --git a/quickjs/examples/pi_bigdecimal.js b/quickjs/examples/pi_bigdecimal.js deleted file mode 100644 index 6a416b7..0000000 --- a/quickjs/examples/pi_bigdecimal.js +++ /dev/null @@ -1,68 +0,0 @@ -/* - * PI computation in Javascript using the QuickJS bigdecimal type - * (decimal floating point) - */ -"use strict"; - -/* compute PI with a precision of 'prec' digits */ -function calc_pi(prec) { - const CHUD_A = 13591409m; - const CHUD_B = 545140134m; - const CHUD_C = 640320m; - const CHUD_C3 = 10939058860032000m; /* C^3/24 */ - const CHUD_DIGITS_PER_TERM = 14.18164746272548; /* log10(C/12)*3 */ - - /* return [P, Q, G] */ - function chud_bs(a, b, need_G) { - var c, P, Q, G, P1, Q1, G1, P2, Q2, G2, b1; - if (a == (b - 1n)) { - b1 = BigDecimal(b); - G = (2m * b1 - 1m) * (6m * b1 - 1m) * (6m * b1 - 5m); - P = G * (CHUD_B * b1 + CHUD_A); - if (b & 1n) - P = -P; - G = G; - Q = b1 * b1 * b1 * CHUD_C3; - } else { - c = (a + b) >> 1n; - [P1, Q1, G1] = chud_bs(a, c, true); - [P2, Q2, G2] = chud_bs(c, b, need_G); - P = P1 * Q2 + P2 * G1; - Q = Q1 * Q2; - if (need_G) - G = G1 * G2; - else - G = 0m; - } - return [P, Q, G]; - } - - var n, P, Q, G; - /* number of serie terms */ - n = BigInt(Math.ceil(prec / CHUD_DIGITS_PER_TERM)) + 10n; - [P, Q, G] = chud_bs(0n, n, false); - Q = BigDecimal.div(Q, (P + Q * CHUD_A), - { roundingMode: "half-even", - maximumSignificantDigits: prec }); - G = (CHUD_C / 12m) * BigDecimal.sqrt(CHUD_C, - { roundingMode: "half-even", - maximumSignificantDigits: prec }); - return Q * G; -} - -(function() { - var r, n_digits, n_bits; - if (typeof scriptArgs != "undefined") { - if (scriptArgs.length < 2) { - print("usage: pi n_digits"); - return; - } - n_digits = scriptArgs[1] | 0; - } else { - n_digits = 1000; - } - /* we add more digits to reduce the probability of bad rounding for - the last digits */ - r = calc_pi(n_digits + 20); - print(r.toFixed(n_digits, "down")); -})(); diff --git a/quickjs/examples/pi_bigfloat.js b/quickjs/examples/pi_bigfloat.js deleted file mode 100644 index 2bcda22..0000000 --- a/quickjs/examples/pi_bigfloat.js +++ /dev/null @@ -1,66 +0,0 @@ -/* - * PI computation in Javascript using the QuickJS bigfloat type - * (binary floating point) - */ -"use strict"; - -/* compute PI with a precision of 'prec' bits */ -function calc_pi() { - const CHUD_A = 13591409n; - const CHUD_B = 545140134n; - const CHUD_C = 640320n; - const CHUD_C3 = 10939058860032000n; /* C^3/24 */ - const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ - - /* return [P, Q, G] */ - function chud_bs(a, b, need_G) { - var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; - if (a == (b - 1n)) { - G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); - P = BigFloat(G * (CHUD_B * b + CHUD_A)); - if (b & 1n) - P = -P; - G = BigFloat(G); - Q = BigFloat(b * b * b * CHUD_C3); - } else { - c = (a + b) >> 1n; - [P1, Q1, G1] = chud_bs(a, c, true); - [P2, Q2, G2] = chud_bs(c, b, need_G); - P = P1 * Q2 + P2 * G1; - Q = Q1 * Q2; - if (need_G) - G = G1 * G2; - else - G = 0l; - } - return [P, Q, G]; - } - - var n, P, Q, G; - /* number of serie terms */ - n = BigInt(Math.ceil(BigFloatEnv.prec / CHUD_BITS_PER_TERM)) + 10n; - [P, Q, G] = chud_bs(0n, n, false); - Q = Q / (P + Q * BigFloat(CHUD_A)); - G = BigFloat((CHUD_C / 12n)) * BigFloat.sqrt(BigFloat(CHUD_C)); - return Q * G; -} - -(function() { - var r, n_digits, n_bits; - if (typeof scriptArgs != "undefined") { - if (scriptArgs.length < 2) { - print("usage: pi n_digits"); - return; - } - n_digits = scriptArgs[1]; - } else { - n_digits = 1000; - } - n_bits = Math.ceil(n_digits * Math.log2(10)); - /* we add more bits to reduce the probability of bad rounding for - the last digits */ - BigFloatEnv.setPrec( () => { - r = calc_pi(); - print(r.toFixed(n_digits, BigFloatEnv.RNDZ)); - }, n_bits + 32); -})(); diff --git a/quickjs/examples/pi_bigint.js b/quickjs/examples/pi_bigint.js deleted file mode 100644 index cbbb2c4..0000000 --- a/quickjs/examples/pi_bigint.js +++ /dev/null @@ -1,118 +0,0 @@ -/* - * PI computation in Javascript using the BigInt type - */ -"use strict"; - -/* return floor(log2(a)) for a > 0 and 0 for a = 0 */ -function floor_log2(a) -{ - var k_max, a1, k, i; - k_max = 0n; - while ((a >> (2n ** k_max)) != 0n) { - k_max++; - } - k = 0n; - a1 = a; - for(i = k_max - 1n; i >= 0n; i--) { - a1 = a >> (2n ** i); - if (a1 != 0n) { - a = a1; - k |= (1n << i); - } - } - return k; -} - -/* return ceil(log2(a)) for a > 0 */ -function ceil_log2(a) -{ - return floor_log2(a - 1n) + 1n; -} - -/* return floor(sqrt(a)) (not efficient but simple) */ -function int_sqrt(a) -{ - var l, u, s; - if (a == 0n) - return a; - l = ceil_log2(a); - u = 1n << ((l + 1n) / 2n); - /* u >= floor(sqrt(a)) */ - for(;;) { - s = u; - u = ((a / s) + s) / 2n; - if (u >= s) - break; - } - return s; -} - -/* return pi * 2**prec */ -function calc_pi(prec) { - const CHUD_A = 13591409n; - const CHUD_B = 545140134n; - const CHUD_C = 640320n; - const CHUD_C3 = 10939058860032000n; /* C^3/24 */ - const CHUD_BITS_PER_TERM = 47.11041313821584202247; /* log2(C/12)*3 */ - - /* return [P, Q, G] */ - function chud_bs(a, b, need_G) { - var c, P, Q, G, P1, Q1, G1, P2, Q2, G2; - if (a == (b - 1n)) { - G = (2n * b - 1n) * (6n * b - 1n) * (6n * b - 5n); - P = G * (CHUD_B * b + CHUD_A); - if (b & 1n) - P = -P; - Q = b * b * b * CHUD_C3; - } else { - c = (a + b) >> 1n; - [P1, Q1, G1] = chud_bs(a, c, true); - [P2, Q2, G2] = chud_bs(c, b, need_G); - P = P1 * Q2 + P2 * G1; - Q = Q1 * Q2; - if (need_G) - G = G1 * G2; - else - G = 0n; - } - return [P, Q, G]; - } - - var n, P, Q, G; - /* number of serie terms */ - n = BigInt(Math.ceil(Number(prec) / CHUD_BITS_PER_TERM)) + 10n; - [P, Q, G] = chud_bs(0n, n, false); - Q = (CHUD_C / 12n) * (Q << prec) / (P + Q * CHUD_A); - G = int_sqrt(CHUD_C << (2n * prec)); - return (Q * G) >> prec; -} - -function main(args) { - var r, n_digits, n_bits, out; - if (args.length < 1) { - print("usage: pi n_digits"); - return; - } - n_digits = args[0] | 0; - - /* we add more bits to reduce the probability of bad rounding for - the last digits */ - n_bits = BigInt(Math.ceil(n_digits * Math.log2(10))) + 32n; - r = calc_pi(n_bits); - r = ((10n ** BigInt(n_digits)) * r) >> n_bits; - out = r.toString(); - print(out[0] + "." + out.slice(1)); -} - -var args; -if (typeof scriptArgs != "undefined") { - args = scriptArgs; - args.shift(); -} else if (typeof arguments != "undefined") { - args = arguments; -} else { - /* default: 1000 digits */ - args=[1000]; -} - -main(args); diff --git a/quickjs/examples/point.c b/quickjs/examples/point.c deleted file mode 100644 index fbe2ce1..0000000 --- a/quickjs/examples/point.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * QuickJS: Example of C module with a class - * - * Copyright (c) 2019 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "../quickjs.h" -#include - -#define countof(x) (sizeof(x) / sizeof((x)[0])) - -/* Point Class */ - -typedef struct { - int x; - int y; -} JSPointData; - -static JSClassID js_point_class_id; - -static void js_point_finalizer(JSRuntime *rt, JSValue val) -{ - JSPointData *s = JS_GetOpaque(val, js_point_class_id); - /* Note: 's' can be NULL in case JS_SetOpaque() was not called */ - js_free_rt(rt, s); -} - -static JSValue js_point_ctor(JSContext *ctx, - JSValueConst new_target, - int argc, JSValueConst *argv) -{ - JSPointData *s; - JSValue obj = JS_UNDEFINED; - JSValue proto; - - s = js_mallocz(ctx, sizeof(*s)); - if (!s) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &s->x, argv[0])) - goto fail; - if (JS_ToInt32(ctx, &s->y, argv[1])) - goto fail; - /* using new_target to get the prototype is necessary when the - class is extended. */ - proto = JS_GetPropertyStr(ctx, new_target, "prototype"); - if (JS_IsException(proto)) - goto fail; - obj = JS_NewObjectProtoClass(ctx, proto, js_point_class_id); - JS_FreeValue(ctx, proto); - if (JS_IsException(obj)) - goto fail; - JS_SetOpaque(obj, s); - return obj; - fail: - js_free(ctx, s); - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - -static JSValue js_point_get_xy(JSContext *ctx, JSValueConst this_val, int magic) -{ - JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); - if (!s) - return JS_EXCEPTION; - if (magic == 0) - return JS_NewInt32(ctx, s->x); - else - return JS_NewInt32(ctx, s->y); -} - -static JSValue js_point_set_xy(JSContext *ctx, JSValueConst this_val, JSValue val, int magic) -{ - JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); - int v; - if (!s) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &v, val)) - return JS_EXCEPTION; - if (magic == 0) - s->x = v; - else - s->y = v; - return JS_UNDEFINED; -} - -static JSValue js_point_norm(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSPointData *s = JS_GetOpaque2(ctx, this_val, js_point_class_id); - if (!s) - return JS_EXCEPTION; - return JS_NewFloat64(ctx, sqrt((double)s->x * s->x + (double)s->y * s->y)); -} - -static JSClassDef js_point_class = { - "Point", - .finalizer = js_point_finalizer, -}; - -static const JSCFunctionListEntry js_point_proto_funcs[] = { - JS_CGETSET_MAGIC_DEF("x", js_point_get_xy, js_point_set_xy, 0), - JS_CGETSET_MAGIC_DEF("y", js_point_get_xy, js_point_set_xy, 1), - JS_CFUNC_DEF("norm", 0, js_point_norm), -}; - -static int js_point_init(JSContext *ctx, JSModuleDef *m) -{ - JSValue point_proto, point_class; - - /* create the Point class */ - JS_NewClassID(&js_point_class_id); - JS_NewClass(JS_GetRuntime(ctx), js_point_class_id, &js_point_class); - - point_proto = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, point_proto, js_point_proto_funcs, countof(js_point_proto_funcs)); - - point_class = JS_NewCFunction2(ctx, js_point_ctor, "Point", 2, JS_CFUNC_constructor, 0); - /* set proto.constructor and ctor.prototype */ - JS_SetConstructor(ctx, point_class, point_proto); - JS_SetClassProto(ctx, js_point_class_id, point_proto); - - JS_SetModuleExport(ctx, m, "Point", point_class); - return 0; -} - -JSModuleDef *js_init_module(JSContext *ctx, const char *module_name) -{ - JSModuleDef *m; - m = JS_NewCModule(ctx, module_name, js_point_init); - if (!m) - return NULL; - JS_AddModuleExport(ctx, m, "Point"); - return m; -} diff --git a/quickjs/examples/test_fib.js b/quickjs/examples/test_fib.js deleted file mode 100644 index 70d26bd..0000000 --- a/quickjs/examples/test_fib.js +++ /dev/null @@ -1,6 +0,0 @@ -/* example of JS module importing a C module */ - -import { fib } from "./fib.so"; - -console.log("Hello World"); -console.log("fib(10)=", fib(10)); diff --git a/quickjs/examples/test_point.js b/quickjs/examples/test_point.js deleted file mode 100644 index 0659bc3..0000000 --- a/quickjs/examples/test_point.js +++ /dev/null @@ -1,40 +0,0 @@ -/* example of JS module importing a C module */ -import { Point } from "./point.so"; - -function assert(b, str) -{ - if (b) { - return; - } else { - throw Error("assertion failed: " + str); - } -} - -class ColorPoint extends Point { - constructor(x, y, color) { - super(x, y); - this.color = color; - } - get_color() { - return this.color; - } -}; - -function main() -{ - var pt, pt2; - - pt = new Point(2, 3); - assert(pt.x === 2); - assert(pt.y === 3); - pt.x = 4; - assert(pt.x === 4); - assert(pt.norm() == 5); - - pt2 = new ColorPoint(2, 3, 0xffffff); - assert(pt2.x === 2); - assert(pt2.color === 0xffffff); - assert(pt2.get_color() === 0xffffff); -} - -main(); diff --git a/quickjs/qjs.c b/quickjs/qjs.c deleted file mode 100644 index e4a4a0a..0000000 --- a/quickjs/qjs.c +++ /dev/null @@ -1,570 +0,0 @@ - /* - * QuickJS stand alone interpreter - * - * Copyright (c) 2017-2021 Fabrice Bellard - * Copyright (c) 2017-2021 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if defined(__APPLE__) -#include -#elif defined(__linux__) -#include -#endif - -#include "cutils.h" -#include "quickjs-libc.h" - -extern const uint8_t qjsc_repl[]; -extern const uint32_t qjsc_repl_size; -#ifdef CONFIG_BIGNUM -extern const uint8_t qjsc_qjscalc[]; -extern const uint32_t qjsc_qjscalc_size; -static int bignum_ext; -#endif - -static int eval_buf(JSContext *ctx, const void *buf, int buf_len, - const char *filename, int eval_flags) -{ - JSValue val; - int ret; - - if ((eval_flags & JS_EVAL_TYPE_MASK) == JS_EVAL_TYPE_MODULE) { - /* for the modules, we compile then run to be able to set - import.meta */ - val = JS_Eval(ctx, buf, buf_len, filename, - eval_flags | JS_EVAL_FLAG_COMPILE_ONLY); - if (!JS_IsException(val)) { - js_module_set_import_meta(ctx, val, TRUE, TRUE); - val = JS_EvalFunction(ctx, val); - } - } else { - val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); - } - if (JS_IsException(val)) { - js_std_dump_error(ctx); - ret = -1; - } else { - ret = 0; - } - JS_FreeValue(ctx, val); - return ret; -} - -static int eval_file(JSContext *ctx, const char *filename, int module) -{ - uint8_t *buf; - int ret, eval_flags; - size_t buf_len; - - buf = js_load_file(ctx, &buf_len, filename); - if (!buf) { - perror(filename); - exit(1); - } - - if (module < 0) { - module = (has_suffix(filename, ".mjs") || - JS_DetectModule((const char *)buf, buf_len)); - } - if (module) - eval_flags = JS_EVAL_TYPE_MODULE; - else - eval_flags = JS_EVAL_TYPE_GLOBAL; - ret = eval_buf(ctx, buf, buf_len, filename, eval_flags); - js_free(ctx, buf); - return ret; -} - -/* also used to initialize the worker context */ -static JSContext *JS_NewCustomContext(JSRuntime *rt) -{ - JSContext *ctx; - ctx = JS_NewContext(rt); - if (!ctx) - return NULL; -#ifdef CONFIG_BIGNUM - if (bignum_ext) { - JS_AddIntrinsicBigFloat(ctx); - JS_AddIntrinsicBigDecimal(ctx); - JS_AddIntrinsicOperators(ctx); - JS_EnableBignumExt(ctx, TRUE); - } -#endif - /* system modules */ - js_init_module_std(ctx, "std"); - js_init_module_os(ctx, "os"); - return ctx; -} - -#if defined(__APPLE__) -#define MALLOC_OVERHEAD 0 -#else -#define MALLOC_OVERHEAD 8 -#endif - -struct trace_malloc_data { - uint8_t *base; -}; - -static inline unsigned long long js_trace_malloc_ptr_offset(uint8_t *ptr, - struct trace_malloc_data *dp) -{ - return ptr - dp->base; -} - -/* default memory allocation functions with memory limitation */ -static inline size_t js_trace_malloc_usable_size(void *ptr) -{ -#if defined(__APPLE__) - return malloc_size(ptr); -#elif defined(_WIN32) - return _msize(ptr); -#elif defined(EMSCRIPTEN) - return 0; -#elif defined(__linux__) - return malloc_usable_size(ptr); -#else - /* change this to `return 0;` if compilation fails */ - return malloc_usable_size(ptr); -#endif -} - -static void -#ifdef _WIN32 -/* mingw printf is used */ -__attribute__((format(gnu_printf, 2, 3))) -#else -__attribute__((format(printf, 2, 3))) -#endif - js_trace_malloc_printf(JSMallocState *s, const char *fmt, ...) -{ - va_list ap; - int c; - - va_start(ap, fmt); - while ((c = *fmt++) != '\0') { - if (c == '%') { - /* only handle %p and %zd */ - if (*fmt == 'p') { - uint8_t *ptr = va_arg(ap, void *); - if (ptr == NULL) { - printf("NULL"); - } else { - printf("H%+06lld.%zd", - js_trace_malloc_ptr_offset(ptr, s->opaque), - js_trace_malloc_usable_size(ptr)); - } - fmt++; - continue; - } - if (fmt[0] == 'z' && fmt[1] == 'd') { - size_t sz = va_arg(ap, size_t); - printf("%zd", sz); - fmt += 2; - continue; - } - } - putc(c, stdout); - } - va_end(ap); -} - -static void js_trace_malloc_init(struct trace_malloc_data *s) -{ - free(s->base = malloc(8)); -} - -static void *js_trace_malloc(JSMallocState *s, size_t size) -{ - void *ptr; - - /* Do not allocate zero bytes: behavior is platform dependent */ - assert(size != 0); - - if (unlikely(s->malloc_size + size > s->malloc_limit)) - return NULL; - ptr = malloc(size); - js_trace_malloc_printf(s, "A %zd -> %p\n", size, ptr); - if (ptr) { - s->malloc_count++; - s->malloc_size += js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; - } - return ptr; -} - -static void js_trace_free(JSMallocState *s, void *ptr) -{ - if (!ptr) - return; - - js_trace_malloc_printf(s, "F %p\n", ptr); - s->malloc_count--; - s->malloc_size -= js_trace_malloc_usable_size(ptr) + MALLOC_OVERHEAD; - free(ptr); -} - -static void *js_trace_realloc(JSMallocState *s, void *ptr, size_t size) -{ - size_t old_size; - - if (!ptr) { - if (size == 0) - return NULL; - return js_trace_malloc(s, size); - } - old_size = js_trace_malloc_usable_size(ptr); - if (size == 0) { - js_trace_malloc_printf(s, "R %zd %p\n", size, ptr); - s->malloc_count--; - s->malloc_size -= old_size + MALLOC_OVERHEAD; - free(ptr); - return NULL; - } - if (s->malloc_size + size - old_size > s->malloc_limit) - return NULL; - - js_trace_malloc_printf(s, "R %zd %p", size, ptr); - - ptr = realloc(ptr, size); - js_trace_malloc_printf(s, " -> %p\n", ptr); - if (ptr) { - s->malloc_size += js_trace_malloc_usable_size(ptr) - old_size; - } - return ptr; -} - -static const JSMallocFunctions trace_mf = { - js_trace_malloc, - js_trace_free, - js_trace_realloc, -#if defined(__APPLE__) - malloc_size, -#elif defined(_WIN32) - (size_t (*)(const void *))_msize, -#elif defined(EMSCRIPTEN) - NULL, -#elif defined(__linux__) - (size_t (*)(const void *))malloc_usable_size, -#else - /* change this to `NULL,` if compilation fails */ - malloc_usable_size, -#endif -}; - -#define PROG_NAME "qjs" - -void help(void) -{ - printf("QuickJS version " CONFIG_VERSION "\n" - "usage: " PROG_NAME " [options] [file [args]]\n" - "-h --help list options\n" - "-e --eval EXPR evaluate EXPR\n" - "-i --interactive go to interactive mode\n" - "-m --module load as ES6 module (default=autodetect)\n" - " --script load as ES6 script (default=autodetect)\n" - "-I --include file include an additional file\n" - " --std make 'std' and 'os' available to the loaded script\n" -#ifdef CONFIG_BIGNUM - " --bignum enable the bignum extensions (BigFloat, BigDecimal)\n" - " --qjscalc load the QJSCalc runtime (default if invoked as qjscalc)\n" -#endif - "-T --trace trace memory allocation\n" - "-d --dump dump the memory usage stats\n" - " --memory-limit n limit the memory usage to 'n' bytes\n" - " --stack-size n limit the stack size to 'n' bytes\n" - " --unhandled-rejection dump unhandled promise rejections\n" - "-q --quit just instantiate the interpreter and quit\n"); - exit(1); -} - -int main(int argc, char **argv) -{ - JSRuntime *rt; - JSContext *ctx; - struct trace_malloc_data trace_data = { NULL }; - int optind; - char *expr = NULL; - int interactive = 0; - int dump_memory = 0; - int trace_memory = 0; - int empty_run = 0; - int module = -1; - int load_std = 0; - int dump_unhandled_promise_rejection = 0; - size_t memory_limit = 0; - char *include_list[32]; - int i, include_count = 0; -#ifdef CONFIG_BIGNUM - int load_jscalc; -#endif - size_t stack_size = 0; - -#ifdef CONFIG_BIGNUM - /* load jscalc runtime if invoked as 'qjscalc' */ - { - const char *p, *exename; - exename = argv[0]; - p = strrchr(exename, '/'); - if (p) - exename = p + 1; - load_jscalc = !strcmp(exename, "qjscalc"); - } -#endif - - /* cannot use getopt because we want to pass the command line to - the script */ - optind = 1; - while (optind < argc && *argv[optind] == '-') { - char *arg = argv[optind] + 1; - const char *longopt = ""; - /* a single - is not an option, it also stops argument scanning */ - if (!*arg) - break; - optind++; - if (*arg == '-') { - longopt = arg + 1; - arg += strlen(arg); - /* -- stops argument scanning */ - if (!*longopt) - break; - } - for (; *arg || *longopt; longopt = "") { - char opt = *arg; - if (opt) - arg++; - if (opt == 'h' || opt == '?' || !strcmp(longopt, "help")) { - help(); - continue; - } - if (opt == 'e' || !strcmp(longopt, "eval")) { - if (*arg) { - expr = arg; - break; - } - if (optind < argc) { - expr = argv[optind++]; - break; - } - fprintf(stderr, "qjs: missing expression for -e\n"); - exit(2); - } - if (opt == 'I' || !strcmp(longopt, "include")) { - if (optind >= argc) { - fprintf(stderr, "expecting filename"); - exit(1); - } - if (include_count >= countof(include_list)) { - fprintf(stderr, "too many included files"); - exit(1); - } - include_list[include_count++] = argv[optind++]; - continue; - } - if (opt == 'i' || !strcmp(longopt, "interactive")) { - interactive++; - continue; - } - if (opt == 'm' || !strcmp(longopt, "module")) { - module = 1; - continue; - } - if (!strcmp(longopt, "script")) { - module = 0; - continue; - } - if (opt == 'd' || !strcmp(longopt, "dump")) { - dump_memory++; - continue; - } - if (opt == 'T' || !strcmp(longopt, "trace")) { - trace_memory++; - continue; - } - if (!strcmp(longopt, "std")) { - load_std = 1; - continue; - } - if (!strcmp(longopt, "unhandled-rejection")) { - dump_unhandled_promise_rejection = 1; - continue; - } -#ifdef CONFIG_BIGNUM - if (!strcmp(longopt, "bignum")) { - bignum_ext = 1; - continue; - } - if (!strcmp(longopt, "qjscalc")) { - load_jscalc = 1; - continue; - } -#endif - if (opt == 'q' || !strcmp(longopt, "quit")) { - empty_run++; - continue; - } - if (!strcmp(longopt, "memory-limit")) { - if (optind >= argc) { - fprintf(stderr, "expecting memory limit"); - exit(1); - } - memory_limit = (size_t)strtod(argv[optind++], NULL); - continue; - } - if (!strcmp(longopt, "stack-size")) { - if (optind >= argc) { - fprintf(stderr, "expecting stack size"); - exit(1); - } - stack_size = (size_t)strtod(argv[optind++], NULL); - continue; - } - if (opt) { - fprintf(stderr, "qjs: unknown option '-%c'\n", opt); - } else { - fprintf(stderr, "qjs: unknown option '--%s'\n", longopt); - } - help(); - } - } - - if (load_jscalc) - bignum_ext = 1; - - if (trace_memory) { - js_trace_malloc_init(&trace_data); - rt = JS_NewRuntime2(&trace_mf, &trace_data); - } else { - rt = JS_NewRuntime(); - } - if (!rt) { - fprintf(stderr, "qjs: cannot allocate JS runtime\n"); - exit(2); - } - if (memory_limit != 0) - JS_SetMemoryLimit(rt, memory_limit); - if (stack_size != 0) - JS_SetMaxStackSize(rt, stack_size); - js_std_set_worker_new_context_func(JS_NewCustomContext); - js_std_init_handlers(rt); - ctx = JS_NewCustomContext(rt); - if (!ctx) { - fprintf(stderr, "qjs: cannot allocate JS context\n"); - exit(2); - } - - /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL); - - if (dump_unhandled_promise_rejection) { - JS_SetHostPromiseRejectionTracker(rt, js_std_promise_rejection_tracker, - NULL); - } - - if (!empty_run) { -#ifdef CONFIG_BIGNUM - if (load_jscalc) { - js_std_eval_binary(ctx, qjsc_qjscalc, qjsc_qjscalc_size, 0); - } -#endif - js_std_add_helpers(ctx, argc - optind, argv + optind); - - /* make 'std' and 'os' visible to non module code */ - if (load_std) { - const char *str = "import * as std from 'std';\n" - "import * as os from 'os';\n" - "globalThis.std = std;\n" - "globalThis.os = os;\n"; - eval_buf(ctx, str, strlen(str), "", JS_EVAL_TYPE_MODULE); - } - - for(i = 0; i < include_count; i++) { - if (eval_file(ctx, include_list[i], module)) - goto fail; - } - - if (expr) { - if (eval_buf(ctx, expr, strlen(expr), "", 0)) - goto fail; - } else - if (optind >= argc) { - /* interactive mode */ - interactive = 1; - } else { - const char *filename; - filename = argv[optind]; - if (eval_file(ctx, filename, module)) - goto fail; - } - if (interactive) { - js_std_eval_binary(ctx, qjsc_repl, qjsc_repl_size, 0); - } - js_std_loop(ctx); - } - - if (dump_memory) { - JSMemoryUsage stats; - JS_ComputeMemoryUsage(rt, &stats); - JS_DumpMemoryUsage(stdout, &stats, rt); - } - js_std_free_handlers(rt); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - - if (empty_run && dump_memory) { - clock_t t[5]; - double best[5]; - int i, j; - for (i = 0; i < 100; i++) { - t[0] = clock(); - rt = JS_NewRuntime(); - t[1] = clock(); - ctx = JS_NewContext(rt); - t[2] = clock(); - JS_FreeContext(ctx); - t[3] = clock(); - JS_FreeRuntime(rt); - t[4] = clock(); - for (j = 4; j > 0; j--) { - double ms = 1000.0 * (t[j] - t[j - 1]) / CLOCKS_PER_SEC; - if (i == 0 || best[j] > ms) - best[j] = ms; - } - } - printf("\nInstantiation times (ms): %.3f = %.3f+%.3f+%.3f+%.3f\n", - best[1] + best[2] + best[3] + best[4], - best[1], best[2], best[3], best[4]); - } - return 0; - fail: - js_std_free_handlers(rt); - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return 1; -} diff --git a/quickjs/qjsc.c b/quickjs/qjsc.c deleted file mode 100644 index b9f1e4c..0000000 --- a/quickjs/qjsc.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * QuickJS command line compiler - * - * Copyright (c) 2018-2021 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#if !defined(_WIN32) -#include -#endif - -#include "cutils.h" -#include "quickjs-libc.h" - -typedef struct { - char *name; - char *short_name; - int flags; -} namelist_entry_t; - -typedef struct namelist_t { - namelist_entry_t *array; - int count; - int size; -} namelist_t; - -typedef struct { - const char *option_name; - const char *init_name; -} FeatureEntry; - -static namelist_t cname_list; -static namelist_t cmodule_list; -static namelist_t init_module_list; -static uint64_t feature_bitmap; -static FILE *outfile; -static BOOL byte_swap; -static BOOL dynamic_export; -static const char *c_ident_prefix = "qjsc_"; - -#define FE_ALL (-1) - -static const FeatureEntry feature_list[] = { - { "date", "Date" }, - { "eval", "Eval" }, - { "string-normalize", "StringNormalize" }, - { "regexp", "RegExp" }, - { "json", "JSON" }, - { "proxy", "Proxy" }, - { "map", "MapSet" }, - { "typedarray", "TypedArrays" }, - { "promise", "Promise" }, -#define FE_MODULE_LOADER 9 - { "module-loader", NULL }, -#ifdef CONFIG_BIGNUM - { "bigint", "BigInt" }, -#endif -}; - -void namelist_add(namelist_t *lp, const char *name, const char *short_name, - int flags) -{ - namelist_entry_t *e; - if (lp->count == lp->size) { - size_t newsize = lp->size + (lp->size >> 1) + 4; - namelist_entry_t *a = - realloc(lp->array, sizeof(lp->array[0]) * newsize); - /* XXX: check for realloc failure */ - lp->array = a; - lp->size = newsize; - } - e = &lp->array[lp->count++]; - e->name = strdup(name); - if (short_name) - e->short_name = strdup(short_name); - else - e->short_name = NULL; - e->flags = flags; -} - -void namelist_free(namelist_t *lp) -{ - while (lp->count > 0) { - namelist_entry_t *e = &lp->array[--lp->count]; - free(e->name); - free(e->short_name); - } - free(lp->array); - lp->array = NULL; - lp->size = 0; -} - -namelist_entry_t *namelist_find(namelist_t *lp, const char *name) -{ - int i; - for(i = 0; i < lp->count; i++) { - namelist_entry_t *e = &lp->array[i]; - if (!strcmp(e->name, name)) - return e; - } - return NULL; -} - -static void get_c_name(char *buf, size_t buf_size, const char *file) -{ - const char *p, *r; - size_t len, i; - int c; - char *q; - - p = strrchr(file, '/'); - if (!p) - p = file; - else - p++; - r = strrchr(p, '.'); - if (!r) - len = strlen(p); - else - len = r - p; - pstrcpy(buf, buf_size, c_ident_prefix); - q = buf + strlen(buf); - for(i = 0; i < len; i++) { - c = p[i]; - if (!((c >= '0' && c <= '9') || - (c >= 'A' && c <= 'Z') || - (c >= 'a' && c <= 'z'))) { - c = '_'; - } - if ((q - buf) < buf_size - 1) - *q++ = c; - } - *q = '\0'; -} - -static void dump_hex(FILE *f, const uint8_t *buf, size_t len) -{ - size_t i, col; - col = 0; - for(i = 0; i < len; i++) { - fprintf(f, " 0x%02x,", buf[i]); - if (++col == 8) { - fprintf(f, "\n"); - col = 0; - } - } - if (col != 0) - fprintf(f, "\n"); -} - -static void output_object_code(JSContext *ctx, - FILE *fo, JSValueConst obj, const char *c_name, - BOOL load_only) -{ - uint8_t *out_buf; - size_t out_buf_len; - int flags; - flags = JS_WRITE_OBJ_BYTECODE; - if (byte_swap) - flags |= JS_WRITE_OBJ_BSWAP; - out_buf = JS_WriteObject(ctx, &out_buf_len, obj, flags); - if (!out_buf) { - js_std_dump_error(ctx); - exit(1); - } - - namelist_add(&cname_list, c_name, NULL, load_only); - - fprintf(fo, "const uint32_t %s_size = %u;\n\n", - c_name, (unsigned int)out_buf_len); - fprintf(fo, "const uint8_t %s[%u] = {\n", - c_name, (unsigned int)out_buf_len); - dump_hex(fo, out_buf, out_buf_len); - fprintf(fo, "};\n\n"); - - js_free(ctx, out_buf); -} - -static int js_module_dummy_init(JSContext *ctx, JSModuleDef *m) -{ - /* should never be called when compiling JS code */ - abort(); -} - -static void find_unique_cname(char *cname, size_t cname_size) -{ - char cname1[1024]; - int suffix_num; - size_t len, max_len; - assert(cname_size >= 32); - /* find a C name not matching an existing module C name by - adding a numeric suffix */ - len = strlen(cname); - max_len = cname_size - 16; - if (len > max_len) - cname[max_len] = '\0'; - suffix_num = 1; - for(;;) { - snprintf(cname1, sizeof(cname1), "%s_%d", cname, suffix_num); - if (!namelist_find(&cname_list, cname1)) - break; - suffix_num++; - } - pstrcpy(cname, cname_size, cname1); -} - -JSModuleDef *jsc_module_loader(JSContext *ctx, - const char *module_name, void *opaque) -{ - JSModuleDef *m; - namelist_entry_t *e; - - /* check if it is a declared C or system module */ - e = namelist_find(&cmodule_list, module_name); - if (e) { - /* add in the static init module list */ - namelist_add(&init_module_list, e->name, e->short_name, 0); - /* create a dummy module */ - m = JS_NewCModule(ctx, module_name, js_module_dummy_init); - } else if (has_suffix(module_name, ".so")) { - fprintf(stderr, "Warning: binary module '%s' will be dynamically loaded\n", module_name); - /* create a dummy module */ - m = JS_NewCModule(ctx, module_name, js_module_dummy_init); - /* the resulting executable will export its symbols for the - dynamic library */ - dynamic_export = TRUE; - } else { - size_t buf_len; - uint8_t *buf; - JSValue func_val; - char cname[1024]; - - buf = js_load_file(ctx, &buf_len, module_name); - if (!buf) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s'", - module_name); - return NULL; - } - - /* compile the module */ - func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, - JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); - js_free(ctx, buf); - if (JS_IsException(func_val)) - return NULL; - get_c_name(cname, sizeof(cname), module_name); - if (namelist_find(&cname_list, cname)) { - find_unique_cname(cname, sizeof(cname)); - } - output_object_code(ctx, outfile, func_val, cname, TRUE); - - /* the module is already referenced, so we must free it */ - m = JS_VALUE_GET_PTR(func_val); - JS_FreeValue(ctx, func_val); - } - return m; -} - -static void compile_file(JSContext *ctx, FILE *fo, - const char *filename, - const char *c_name1, - int module) -{ - uint8_t *buf; - char c_name[1024]; - int eval_flags; - JSValue obj; - size_t buf_len; - - buf = js_load_file(ctx, &buf_len, filename); - if (!buf) { - fprintf(stderr, "Could not load '%s'\n", filename); - exit(1); - } - eval_flags = JS_EVAL_FLAG_COMPILE_ONLY; - if (module < 0) { - module = (has_suffix(filename, ".mjs") || - JS_DetectModule((const char *)buf, buf_len)); - } - if (module) - eval_flags |= JS_EVAL_TYPE_MODULE; - else - eval_flags |= JS_EVAL_TYPE_GLOBAL; - obj = JS_Eval(ctx, (const char *)buf, buf_len, filename, eval_flags); - if (JS_IsException(obj)) { - js_std_dump_error(ctx); - exit(1); - } - js_free(ctx, buf); - if (c_name1) { - pstrcpy(c_name, sizeof(c_name), c_name1); - } else { - get_c_name(c_name, sizeof(c_name), filename); - } - output_object_code(ctx, fo, obj, c_name, FALSE); - JS_FreeValue(ctx, obj); -} - -static const char main_c_template1[] = - "int main(int argc, char **argv)\n" - "{\n" - " JSRuntime *rt;\n" - " JSContext *ctx;\n" - " rt = JS_NewRuntime();\n" - " js_std_set_worker_new_context_func(JS_NewCustomContext);\n" - " js_std_init_handlers(rt);\n" - ; - -static const char main_c_template2[] = - " js_std_loop(ctx);\n" - " JS_FreeContext(ctx);\n" - " JS_FreeRuntime(rt);\n" - " return 0;\n" - "}\n"; - -#define PROG_NAME "qjsc" - -void help(void) -{ - printf("QuickJS Compiler version " CONFIG_VERSION "\n" - "usage: " PROG_NAME " [options] [files]\n" - "\n" - "options are:\n" - "-c only output bytecode in a C file\n" - "-e output main() and bytecode in a C file (default = executable output)\n" - "-o output set the output filename\n" - "-N cname set the C name of the generated data\n" - "-m compile as Javascript module (default=autodetect)\n" - "-D module_name compile a dynamically loaded module or worker\n" - "-M module_name[,cname] add initialization code for an external C module\n" - "-x byte swapped output\n" - "-p prefix set the prefix of the generated C names\n" - "-S n set the maximum stack size to 'n' bytes (default=%d)\n", - JS_DEFAULT_STACK_SIZE); -#ifdef CONFIG_LTO - { - int i; - printf("-flto use link time optimization\n"); - printf("-fbignum enable bignum extensions\n"); - printf("-fno-["); - for(i = 0; i < countof(feature_list); i++) { - if (i != 0) - printf("|"); - printf("%s", feature_list[i].option_name); - } - printf("]\n" - " disable selected language features (smaller code size)\n"); - } -#endif - exit(1); -} - -#if defined(CONFIG_CC) && !defined(_WIN32) - -int exec_cmd(char **argv) -{ - int pid, status, ret; - - pid = fork(); - if (pid == 0) { - execvp(argv[0], argv); - exit(1); - } - - for(;;) { - ret = waitpid(pid, &status, 0); - if (ret == pid && WIFEXITED(status)) - break; - } - return WEXITSTATUS(status); -} - -static int output_executable(const char *out_filename, const char *cfilename, - BOOL use_lto, BOOL verbose, const char *exename) -{ - const char *argv[64]; - const char **arg, *bn_suffix, *lto_suffix; - char libjsname[1024]; - char exe_dir[1024], inc_dir[1024], lib_dir[1024], buf[1024], *p; - int ret; - - /* get the directory of the executable */ - pstrcpy(exe_dir, sizeof(exe_dir), exename); - p = strrchr(exe_dir, '/'); - if (p) { - *p = '\0'; - } else { - pstrcpy(exe_dir, sizeof(exe_dir), "."); - } - - /* if 'quickjs.h' is present at the same path as the executable, we - use it as include and lib directory */ - snprintf(buf, sizeof(buf), "%s/quickjs.h", exe_dir); - if (access(buf, R_OK) == 0) { - pstrcpy(inc_dir, sizeof(inc_dir), exe_dir); - pstrcpy(lib_dir, sizeof(lib_dir), exe_dir); - } else { - snprintf(inc_dir, sizeof(inc_dir), "%s/include/quickjs", CONFIG_PREFIX); - snprintf(lib_dir, sizeof(lib_dir), "%s/lib/quickjs", CONFIG_PREFIX); - } - - lto_suffix = ""; - bn_suffix = ""; - - arg = argv; - *arg++ = CONFIG_CC; - *arg++ = "-O2"; -#ifdef CONFIG_LTO - if (use_lto) { - *arg++ = "-flto"; - lto_suffix = ".lto"; - } -#endif - /* XXX: use the executable path to find the includes files and - libraries */ - *arg++ = "-D"; - *arg++ = "_GNU_SOURCE"; - *arg++ = "-I"; - *arg++ = inc_dir; - *arg++ = "-o"; - *arg++ = out_filename; - if (dynamic_export) - *arg++ = "-rdynamic"; - *arg++ = cfilename; - snprintf(libjsname, sizeof(libjsname), "%s/libquickjs%s%s.a", - lib_dir, bn_suffix, lto_suffix); - *arg++ = libjsname; - *arg++ = "-lm"; - *arg++ = "-ldl"; - *arg++ = "-lpthread"; - *arg = NULL; - - if (verbose) { - for(arg = argv; *arg != NULL; arg++) - printf("%s ", *arg); - printf("\n"); - } - - ret = exec_cmd((char **)argv); - unlink(cfilename); - return ret; -} -#else -static int output_executable(const char *out_filename, const char *cfilename, - BOOL use_lto, BOOL verbose, const char *exename) -{ - fprintf(stderr, "Executable output is not supported for this target\n"); - exit(1); - return 0; -} -#endif - - -typedef enum { - OUTPUT_C, - OUTPUT_C_MAIN, - OUTPUT_EXECUTABLE, -} OutputTypeEnum; - -int main(int argc, char **argv) -{ - int c, i, verbose; - const char *out_filename, *cname; - char cfilename[1024]; - FILE *fo; - JSRuntime *rt; - JSContext *ctx; - BOOL use_lto; - int module; - OutputTypeEnum output_type; - size_t stack_size; -#ifdef CONFIG_BIGNUM - BOOL bignum_ext = FALSE; -#endif - namelist_t dynamic_module_list; - - out_filename = NULL; - output_type = OUTPUT_EXECUTABLE; - cname = NULL; - feature_bitmap = FE_ALL; - module = -1; - byte_swap = FALSE; - verbose = 0; - use_lto = FALSE; - stack_size = 0; - memset(&dynamic_module_list, 0, sizeof(dynamic_module_list)); - - /* add system modules */ - namelist_add(&cmodule_list, "std", "std", 0); - namelist_add(&cmodule_list, "os", "os", 0); - - for(;;) { - c = getopt(argc, argv, "ho:cN:f:mxevM:p:S:D:"); - if (c == -1) - break; - switch(c) { - case 'h': - help(); - case 'o': - out_filename = optarg; - break; - case 'c': - output_type = OUTPUT_C; - break; - case 'e': - output_type = OUTPUT_C_MAIN; - break; - case 'N': - cname = optarg; - break; - case 'f': - { - const char *p; - p = optarg; - if (!strcmp(optarg, "lto")) { - use_lto = TRUE; - } else if (strstart(p, "no-", &p)) { - use_lto = TRUE; - for(i = 0; i < countof(feature_list); i++) { - if (!strcmp(p, feature_list[i].option_name)) { - feature_bitmap &= ~((uint64_t)1 << i); - break; - } - } - if (i == countof(feature_list)) - goto bad_feature; - } else -#ifdef CONFIG_BIGNUM - if (!strcmp(optarg, "bignum")) { - bignum_ext = TRUE; - } else -#endif - { - bad_feature: - fprintf(stderr, "unsupported feature: %s\n", optarg); - exit(1); - } - } - break; - case 'm': - module = 1; - break; - case 'M': - { - char *p; - char path[1024]; - char cname[1024]; - pstrcpy(path, sizeof(path), optarg); - p = strchr(path, ','); - if (p) { - *p = '\0'; - pstrcpy(cname, sizeof(cname), p + 1); - } else { - get_c_name(cname, sizeof(cname), path); - } - namelist_add(&cmodule_list, path, cname, 0); - } - break; - case 'D': - namelist_add(&dynamic_module_list, optarg, NULL, 0); - break; - case 'x': - byte_swap = TRUE; - break; - case 'v': - verbose++; - break; - case 'p': - c_ident_prefix = optarg; - break; - case 'S': - stack_size = (size_t)strtod(optarg, NULL); - break; - default: - break; - } - } - - if (optind >= argc) - help(); - - if (!out_filename) { - if (output_type == OUTPUT_EXECUTABLE) { - out_filename = "a.out"; - } else { - out_filename = "out.c"; - } - } - - if (output_type == OUTPUT_EXECUTABLE) { -#if defined(_WIN32) || defined(__ANDROID__) - /* XXX: find a /tmp directory ? */ - snprintf(cfilename, sizeof(cfilename), "out%d.c", getpid()); -#else - snprintf(cfilename, sizeof(cfilename), "/tmp/out%d.c", getpid()); -#endif - } else { - pstrcpy(cfilename, sizeof(cfilename), out_filename); - } - - fo = fopen(cfilename, "w"); - if (!fo) { - perror(cfilename); - exit(1); - } - outfile = fo; - - rt = JS_NewRuntime(); - ctx = JS_NewContext(rt); -#ifdef CONFIG_BIGNUM - if (bignum_ext) { - JS_AddIntrinsicBigFloat(ctx); - JS_AddIntrinsicBigDecimal(ctx); - JS_AddIntrinsicOperators(ctx); - JS_EnableBignumExt(ctx, TRUE); - } -#endif - - /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, jsc_module_loader, NULL); - - fprintf(fo, "/* File generated automatically by the QuickJS compiler. */\n" - "\n" - ); - - if (output_type != OUTPUT_C) { - fprintf(fo, "#include \"quickjs-libc.h\"\n" - "\n" - ); - } else { - fprintf(fo, "#include \n" - "\n" - ); - } - - for(i = optind; i < argc; i++) { - const char *filename = argv[i]; - compile_file(ctx, fo, filename, cname, module); - cname = NULL; - } - - for(i = 0; i < dynamic_module_list.count; i++) { - if (!jsc_module_loader(ctx, dynamic_module_list.array[i].name, NULL)) { - fprintf(stderr, "Could not load dynamic module '%s'\n", - dynamic_module_list.array[i].name); - exit(1); - } - } - - if (output_type != OUTPUT_C) { - fprintf(fo, - "static JSContext *JS_NewCustomContext(JSRuntime *rt)\n" - "{\n" - " JSContext *ctx = JS_NewContextRaw(rt);\n" - " if (!ctx)\n" - " return NULL;\n"); - /* add the basic objects */ - fprintf(fo, " JS_AddIntrinsicBaseObjects(ctx);\n"); - for(i = 0; i < countof(feature_list); i++) { - if ((feature_bitmap & ((uint64_t)1 << i)) && - feature_list[i].init_name) { - fprintf(fo, " JS_AddIntrinsic%s(ctx);\n", - feature_list[i].init_name); - } - } -#ifdef CONFIG_BIGNUM - if (bignum_ext) { - fprintf(fo, - " JS_AddIntrinsicBigFloat(ctx);\n" - " JS_AddIntrinsicBigDecimal(ctx);\n" - " JS_AddIntrinsicOperators(ctx);\n" - " JS_EnableBignumExt(ctx, 1);\n"); - } -#endif - /* add the precompiled modules (XXX: could modify the module - loader instead) */ - for(i = 0; i < init_module_list.count; i++) { - namelist_entry_t *e = &init_module_list.array[i]; - /* initialize the static C modules */ - - fprintf(fo, - " {\n" - " extern JSModuleDef *js_init_module_%s(JSContext *ctx, const char *name);\n" - " js_init_module_%s(ctx, \"%s\");\n" - " }\n", - e->short_name, e->short_name, e->name); - } - for(i = 0; i < cname_list.count; i++) { - namelist_entry_t *e = &cname_list.array[i]; - if (e->flags) { - fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 1);\n", - e->name, e->name); - } - } - fprintf(fo, - " return ctx;\n" - "}\n\n"); - - fputs(main_c_template1, fo); - - if (stack_size != 0) { - fprintf(fo, " JS_SetMaxStackSize(rt, %u);\n", - (unsigned int)stack_size); - } - - /* add the module loader if necessary */ - if (feature_bitmap & (1 << FE_MODULE_LOADER)) { - fprintf(fo, " JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);\n"); - } - - fprintf(fo, - " ctx = JS_NewCustomContext(rt);\n" - " js_std_add_helpers(ctx, argc, argv);\n"); - - for(i = 0; i < cname_list.count; i++) { - namelist_entry_t *e = &cname_list.array[i]; - if (!e->flags) { - fprintf(fo, " js_std_eval_binary(ctx, %s, %s_size, 0);\n", - e->name, e->name); - } - } - fputs(main_c_template2, fo); - } - - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - - fclose(fo); - - if (output_type == OUTPUT_EXECUTABLE) { - return output_executable(out_filename, cfilename, use_lto, verbose, - argv[0]); - } - namelist_free(&cname_list); - namelist_free(&cmodule_list); - namelist_free(&init_module_list); - return 0; -} diff --git a/quickjs/qjscalc.js b/quickjs/qjscalc.js deleted file mode 100644 index b1ad1e8..0000000 --- a/quickjs/qjscalc.js +++ /dev/null @@ -1,2657 +0,0 @@ -/* - * QuickJS Javascript Calculator - * - * Copyright (c) 2017-2020 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -"use strict"; -"use math"; - -var Integer, Float, Fraction, Complex, Mod, Polynomial, PolyMod, RationalFunction, Series, Matrix; - -(function(global) { - global.Integer = global.BigInt; - global.Float = global.BigFloat; - global.algebraicMode = true; - - /* add non enumerable properties */ - function add_props(obj, props) { - var i, val, prop, tab, desc; - tab = Reflect.ownKeys(props); - for(i = 0; i < tab.length; i++) { - prop = tab[i]; - desc = Object.getOwnPropertyDescriptor(props, prop); - desc.enumerable = false; - if ("value" in desc) { - if (typeof desc.value !== "function") { - desc.writable = false; - desc.configurable = false; - } - } else { - /* getter/setter */ - desc.configurable = false; - } - Object.defineProperty(obj, prop, desc); - } - } - - /* same as proto[Symbol.operatorSet] = Operators.create(..op_list) - but allow shortcuts: left: [], right: [] or both - */ - function operators_set(proto, ...op_list) - { - var new_op_list, i, a, j, b, k, obj, tab; - var fields = [ "left", "right" ]; - new_op_list = []; - for(i = 0; i < op_list.length; i++) { - a = op_list[i]; - if (a.left || a.right) { - tab = [ a.left, a.right ]; - delete a.left; - delete a.right; - for(k = 0; k < 2; k++) { - obj = tab[k]; - if (obj) { - if (!Array.isArray(obj)) { - obj = [ obj ]; - } - for(j = 0; j < obj.length; j++) { - b = {}; - Object.assign(b, a); - b[fields[k]] = obj[j]; - new_op_list.push(b); - } - } - } - } else { - new_op_list.push(a); - } - } - proto[Symbol.operatorSet] = - Operators.create.call(null, ...new_op_list); - } - - /* Integer */ - - function generic_pow(a, b) { - var r, is_neg, i; - if (!Integer.isInteger(b)) { - return exp(log(a) * b); - } - if (Array.isArray(a) && !(a instanceof Polynomial || - a instanceof Series)) { - r = idn(Matrix.check_square(a)); - } else { - r = 1; - } - if (b == 0) - return r; - is_neg = false; - if (b < 0) { - is_neg = true; - b = -b; - } - r = a; - for(i = Integer.floorLog2(b) - 1; i >= 0; i--) { - r *= r; - if ((b >> i) & 1) - r *= a; - } - if (is_neg) { - if (typeof r.inverse != "function") - throw "negative powers are not supported for this type"; - r = r.inverse(); - } - return r; - } - - var small_primes = [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499 ]; - - function miller_rabin_test(n, t) { - var d, r, s, i, j, a; - d = n - 1; - s = 0; - while ((d & 1) == 0) { - d >>= 1; - s++; - } - if (small_primes.length < t) - t = small_primes.length; - loop: for(j = 0; j < t; j++) { - a = small_primes[j]; - r = Integer.pmod(a, d, n); - if (r == 1 || r == (n - 1)) - continue; - for(i = 1; i < s; i++) { - r = (r * r) % n; - if (r == 1) - return false; - if (r == (n - 1)) - continue loop; - } - return false; /* n is composite */ - } - return true; /* n is probably prime with probability (1-0.5^t) */ - } - - function fact_rec(a, b) { /* assumes a <= b */ - var i, r; - if ((b - a) <= 5) { - r = a; - for(i = a + 1; i <= b; i++) - r *= i; - return r; - } else { - /* to avoid a quadratic running time it is better to - multiply numbers of similar size */ - i = (a + b) >> 1; - return fact_rec(a, i) * fact_rec(i + 1, b); - } - } - - /* math mode specific quirk to overload the integer division and power */ - Operators.updateBigIntOperators( - { - "/"(a, b) { - if (algebraicMode) { - return Fraction.toFraction(a, b); - } else { - return Float(a) / Float(b); - } - }, - "**"(a, b) { - if (algebraicMode) { - return generic_pow(a, b); - } else { - return Float(a) ** Float(b); - } - } - }); - - add_props(Integer, { - isInteger(a) { - /* integers are represented either as bigint or as number */ - return typeof a === "bigint" || - (typeof a === "number" && Number.isSafeInteger(a)); - }, - gcd(a, b) { - var r; - while (b != 0) { - r = a % b; - a = b; - b = r; - } - return a; - }, - fact(n) { - return n <= 0 ? 1 : fact_rec(1, n); - }, - /* binomial coefficient */ - comb(n, k) { - if (k < 0 || k > n) - return 0; - if (k > n - k) - k = n - k; - if (k == 0) - return 1; - return Integer.tdiv(fact_rec(n - k + 1, n), fact_rec(1, k)); - }, - /* inverse of x modulo y */ - invmod(x, y) { - var q, u, v, a, c, t; - u = x; - v = y; - c = 1; - a = 0; - while (u != 0) { - t = Integer.fdivrem(v, u); - q = t[0]; - v = u; - u = t[1]; - t = c; - c = a - q * c; - a = t; - } - /* v = gcd(x, y) */ - if (v != 1) - throw RangeError("not invertible"); - return a % y; - }, - /* return a ^ b modulo m */ - pmod(a, b, m) { - var r; - if (b == 0) - return 1; - if (b < 0) { - a = Integer.invmod(a, m); - b = -b; - } - r = 1; - for(;;) { - if (b & 1) { - r = (r * a) % m; - } - b >>= 1; - if (b == 0) - break; - a = (a * a) % m; - } - return r; - }, - - /* return true if n is prime (or probably prime with - probability 1-0.5^t) */ - isPrime(n, t) { - var i, d, n1; - if (!Integer.isInteger(n)) - throw TypeError("invalid type"); - if (n <= 1) - return false; - n1 = small_primes.length; - /* XXX: need Integer.sqrt() */ - for(i = 0; i < n1; i++) { - d = small_primes[i]; - if (d == n) - return true; - if (d > n) - return false; - if ((n % d) == 0) - return false; - } - if (n < d * d) - return true; - if (typeof t == "undefined") - t = 64; - return miller_rabin_test(n, t); - }, - nextPrime(n) { - if (!Integer.isInteger(n)) - throw TypeError("invalid type"); - if (n < 1) - n = 1; - for(;;) { - n++; - if (Integer.isPrime(n)) - return n; - } - }, - factor(n) { - var r, d; - if (!Integer.isInteger(n)) - throw TypeError("invalid type"); - r = []; - if (abs(n) <= 1) { - r.push(n); - return r; - } - if (n < 0) { - r.push(-1); - n = -n; - } - - while ((n % 2) == 0) { - n >>= 1; - r.push(2); - } - - d = 3; - while (n != 1) { - if (Integer.isPrime(n)) { - r.push(n); - break; - } - /* we are sure there is at least one divisor, so one test */ - for(;;) { - if ((n % d) == 0) - break; - d += 2; - } - for(;;) { - r.push(d); - n = Integer.tdiv(n, d); - if ((n % d) != 0) - break; - } - } - return r; - }, - }); - - add_props(Integer.prototype, { - inverse() { - return 1 / this; - }, - norm2() { - return this * this; - }, - abs() { - var v = this; - if (v < 0) - v = -v; - return v; - }, - conj() { - return this; - }, - arg() { - if (this >= 0) - return 0; - else - return Float.PI; - }, - exp() { - if (this == 0) - return 1; - else - return Float.exp(this); - }, - log() { - if (this == 1) - return 0; - else - return Float(this).log(); - }, - }); - - /* Fraction */ - - Fraction = function Fraction(a, b) - { - var d, r, obj; - - if (new.target) - throw TypeError("not a constructor"); - if (a instanceof Fraction) - return a; - if (!Integer.isInteger(a)) - throw TypeError("integer expected"); - if (typeof b === "undefined") { - b = 1; - } else { - if (!Integer.isInteger(b)) - throw TypeError("integer expected"); - if (b == 0) - throw RangeError("division by zero"); - d = Integer.gcd(a, b); - if (d != 1) { - a = Integer.tdiv(a, d); - b = Integer.tdiv(b, d); - } - - /* the fractions are normalized with den > 0 */ - if (b < 0) { - a = -a; - b = -b; - } - } - obj = Object.create(Fraction.prototype); - obj.num = a; - obj.den = b; - return obj; - } - - function fraction_add(a, b) { - a = Fraction(a); - b = Fraction(b); - return Fraction.toFraction(a.num * b.den + a.den * b.num, a.den * b.den); - } - function fraction_sub(a, b) { - a = Fraction(a); - b = Fraction(b); - return Fraction.toFraction(a.num * b.den - a.den * b.num, a.den * b.den); - } - function fraction_mul(a, b) { - a = Fraction(a); - b = Fraction(b); - return Fraction.toFraction(a.num * b.num, a.den * b.den); - } - function fraction_div(a, b) { - a = Fraction(a); - b = Fraction(b); - return Fraction.toFraction(a.num * b.den, a.den * b.num); - } - function fraction_mod(a, b) { - var a1 = Fraction(a); - var b1 = Fraction(b); - return a - Integer.ediv(a1.num * b1.den, a1.den * b1.num) * b; - } - function fraction_eq(a, b) { - a = Fraction(a); - b = Fraction(b); - /* we assume the fractions are normalized */ - return (a.num == b.num && a.den == b.den); - } - function fraction_lt(a, b) { - a = Fraction(a); - b = Fraction(b); - return (a.num * b.den < b.num * a.den); - } - - /* operators are needed for fractions */ - function float_add(a, b) { - return Float(a) + Float(b); - } - function float_sub(a, b) { - return Float(a) - Float(b); - } - function float_mul(a, b) { - return Float(a) * Float(b); - } - function float_div(a, b) { - return Float(a) / Float(b); - } - function float_mod(a, b) { - return Float(a) % Float(b); - } - function float_pow(a, b) { - return Float(a) ** Float(b); - } - function float_eq(a, b) { - /* XXX: may be better to use infinite precision for the comparison */ - return Float(a) === Float(b); - } - function float_lt(a, b) { - a = Float(a); - b = Float(b); - /* XXX: may be better to use infinite precision for the comparison */ - if (Float.isNaN(a) || Float.isNaN(b)) - return undefined; - else - return a < b; - } - - operators_set(Fraction.prototype, - { - "+": fraction_add, - "-": fraction_sub, - "*": fraction_mul, - "/": fraction_div, - "%": fraction_mod, - "**": generic_pow, - "==": fraction_eq, - "<": fraction_lt, - "pos"(a) { - return a; - }, - "neg"(a) { - return Fraction(-a.num, a.den); - }, - }, - { - left: [Number, BigInt], - right: [Number, BigInt], - "+": fraction_add, - "-": fraction_sub, - "*": fraction_mul, - "/": fraction_div, - "%": fraction_mod, - "**": generic_pow, - "==": fraction_eq, - "<": fraction_lt, - }, - { - left: Float, - right: Float, - "+": float_add, - "-": float_sub, - "*": float_mul, - "/": float_div, - "%": float_mod, - "**": float_pow, - "==": float_eq, - "<": float_lt, - }); - - add_props(Fraction, { - /* (internal use) simplify 'a' to an integer when possible */ - toFraction(a, b) { - var r = Fraction(a, b); - if (algebraicMode && r.den == 1) - return r.num; - else - return r; - }, - }); - - add_props(Fraction.prototype, { - [Symbol.toPrimitive](hint) { - if (hint === "string") { - return this.toString(); - } else { - return Float(this.num) / this.den; - } - }, - inverse() { - return Fraction(this.den, this.num); - }, - toString() { - return this.num + "/" + this.den; - }, - norm2() { - return this * this; - }, - abs() { - if (this.num < 0) - return -this; - else - return this; - }, - conj() { - return this; - }, - arg() { - if (this.num >= 0) - return 0; - else - return Float.PI; - }, - exp() { - return Float.exp(Float(this)); - }, - log() { - return Float(this).log(); - }, - }); - - /* Number (Float64) */ - - add_props(Number.prototype, { - inverse() { - return 1 / this; - }, - norm2() { - return this * this; - }, - abs() { - return Math.abs(this); - }, - conj() { - return this; - }, - arg() { - if (this >= 0) - return 0; - else - return Float.PI; - }, - exp() { - return Float.exp(this); - }, - log() { - if (this < 0) { - return Complex(this).log(); - } else { - return Float.log(this); - } - }, - }); - - /* Float */ - - var const_tab = []; - - /* we cache the constants for small precisions */ - function get_const(n) { - var t, c, p; - t = const_tab[n]; - p = BigFloatEnv.prec; - if (t && t.prec == p) { - return t.val; - } else { - switch(n) { - case 0: c = Float.exp(1); break; - case 1: c = Float.log(10); break; -// case 2: c = Float.log(2); break; - case 3: c = 1/Float.log(2); break; - case 4: c = 1/Float.log(10); break; -// case 5: c = Float.atan(1) * 4; break; - case 6: c = Float.sqrt(0.5); break; - case 7: c = Float.sqrt(2); break; - } - if (p <= 1024) { - const_tab[n] = { prec: p, val: c }; - } - return c; - } - } - - add_props(Float, { - isFloat(a) { - return typeof a === "number" || typeof a === "bigfloat"; - }, - bestappr(u, b) { - var num1, num0, den1, den0, u, num, den, n; - - if (typeof b === "undefined") - throw TypeError("second argument expected"); - num1 = 1; - num0 = 0; - den1 = 0; - den0 = 1; - for(;;) { - n = Integer(Float.floor(u)); - num = n * num1 + num0; - den = n * den1 + den0; - if (den > b) - break; - u = 1.0 / (u - n); - num0 = num1; - num1 = num; - den0 = den1; - den1 = den; - } - return Fraction(num1, den1); - }, - /* similar constants as Math.x */ - get E() { return get_const(0); }, - get LN10() { return get_const(1); }, -// get LN2() { return get_const(2); }, - get LOG2E() { return get_const(3); }, - get LOG10E() { return get_const(4); }, -// get PI() { return get_const(5); }, - get SQRT1_2() { return get_const(6); }, - get SQRT2() { return get_const(7); }, - }); - - add_props(Float.prototype, { - inverse() { - return 1.0 / this; - }, - norm2() { - return this * this; - }, - abs() { - return Float.abs(this); - }, - conj() { - return this; - }, - arg() { - if (this >= 0) - return 0; - else - return Float.PI; - }, - exp() { - return Float.exp(this); - }, - log() { - if (this < 0) { - return Complex(this).log(); - } else { - return Float.log(this); - } - }, - }); - - /* Complex */ - - Complex = function Complex(re, im) - { - var obj; - if (new.target) - throw TypeError("not a constructor"); - if (re instanceof Complex) - return re; - if (typeof im === "undefined") { - im = 0; - } - obj = Object.create(Complex.prototype); - obj.re = re; - obj.im = im; - return obj; - } - - - function complex_add(a, b) { - a = Complex(a); - b = Complex(b); - return Complex.toComplex(a.re + b.re, a.im + b.im); - } - function complex_sub(a, b) { - a = Complex(a); - b = Complex(b); - return Complex.toComplex(a.re - b.re, a.im - b.im); - } - function complex_mul(a, b) { - a = Complex(a); - b = Complex(b); - return Complex.toComplex(a.re * b.re - a.im * b.im, - a.re * b.im + a.im * b.re); - } - function complex_div(a, b) { - a = Complex(a); - b = Complex(b); - return a * b.inverse(); - } - function complex_eq(a, b) { - a = Complex(a); - b = Complex(b); - return a.re == b.re && a.im == b.im; - } - - operators_set(Complex.prototype, - { - "+": complex_add, - "-": complex_sub, - "*": complex_mul, - "/": complex_div, - "**": generic_pow, - "==": complex_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - return Complex(-a.re, -a.im); - } - }, - { - left: [Number, BigInt, Float, Fraction], - right: [Number, BigInt, Float, Fraction], - "+": complex_add, - "-": complex_sub, - "*": complex_mul, - "/": complex_div, - "**": generic_pow, - "==": complex_eq, - }); - - add_props(Complex, { - /* simplify to real number when possible */ - toComplex(re, im) { - if (algebraicMode && im == 0) - return re; - else - return Complex(re, im); - }, - }); - - add_props(Complex.prototype, { - inverse() { - var c = this.norm2(); - return Complex(this.re / c, -this.im / c); - }, - toString() { - var v, s = "", a = this; - if (a.re != 0) - s += a.re.toString(); - if (a.im == 1) { - if (s != "") - s += "+"; - s += "I"; - } else if (a.im == -1) { - s += "-I"; - } else { - v = a.im.toString(); - if (v[0] != "-" && s != "") - s += "+"; - s += v + "*I"; - } - return s; - }, - norm2() { - return this.re * this.re + this.im * this.im; - }, - abs() { - return Float.sqrt(norm2(this)); - }, - conj() { - return Complex(this.re, -this.im); - }, - arg() { - return Float.atan2(this.im, this.re); - }, - exp() { - var arg = this.im, r = this.re.exp(); - return Complex(r * cos(arg), r * sin(arg)); - }, - log() { - return Complex(abs(this).log(), atan2(this.im, this.re)); - }, - }); - - /* Mod */ - - Mod = function Mod(a, m) { - var obj, t; - if (new.target) - throw TypeError("not a constructor"); - obj = Object.create(Mod.prototype); - if (Integer.isInteger(m)) { - if (m <= 0) - throw RangeError("the modulo cannot be <= 0"); - if (Integer.isInteger(a)) { - a %= m; - } else if (a instanceof Fraction) { - return Mod(a.num, m) / a.den; - } else { - throw TypeError("invalid types"); - } - } else { - throw TypeError("invalid types"); - } - obj.res = a; - obj.mod = m; - return obj; - }; - - function mod_add(a, b) { - if (!(a instanceof Mod)) { - return Mod(a + b.res, b.mod); - } else if (!(b instanceof Mod)) { - return Mod(a.res + b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return Mod(a.res + b.res, a.mod); - } - } - function mod_sub(a, b) { - if (!(a instanceof Mod)) { - return Mod(a - b.res, b.mod); - } else if (!(b instanceof Mod)) { - return Mod(a.res - b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return Mod(a.res - b.res, a.mod); - } - } - function mod_mul(a, b) { - if (!(a instanceof Mod)) { - return Mod(a * b.res, b.mod); - } else if (!(b instanceof Mod)) { - return Mod(a.res * b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return Mod(a.res * b.res, a.mod); - } - } - function mod_div(a, b) { - if (!(b instanceof Mod)) - b = Mod(b, a.mod); - return mod_mul(a, b.inverse()); - } - function mod_eq(a, b) { - return (a.mod == b.mod && a.res == b.res); - } - - operators_set(Mod.prototype, - { - "+": mod_add, - "-": mod_sub, - "*": mod_mul, - "/": mod_div, - "**": generic_pow, - "==": mod_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - return Mod(-a.res, a.mod); - } - }, - { - left: [Number, BigInt, Float, Fraction], - right: [Number, BigInt, Float, Fraction], - "+": mod_add, - "-": mod_sub, - "*": mod_mul, - "/": mod_div, - "**": generic_pow, - }); - - add_props(Mod.prototype, { - inverse() { - var a = this, m = a.mod; - if (Integer.isInteger(m)) { - return Mod(Integer.invmod(a.res, m), m); - } else { - throw TypeError("unsupported type"); - } - }, - toString() { - return "Mod(" + this.res + "," + this.mod + ")"; - }, - }); - - /* Polynomial */ - - function polynomial_is_scalar(a) - { - if (typeof a === "number" || - typeof a === "bigint" || - typeof a === "bigfloat") - return true; - if (a instanceof Fraction || - a instanceof Complex || - a instanceof Mod) - return true; - return false; - } - - Polynomial = function Polynomial(a) - { - if (new.target) - throw TypeError("not a constructor"); - if (a instanceof Polynomial) { - return a; - } else if (Array.isArray(a)) { - if (a.length == 0) - a = [ 0 ]; - Object.setPrototypeOf(a, Polynomial.prototype); - return a.trim(); - } else if (polynomial_is_scalar(a)) { - a = [a]; - Object.setPrototypeOf(a, Polynomial.prototype); - return a; - } else { - throw TypeError("invalid type"); - } - } - - function number_need_paren(c) - { - return !(Integer.isInteger(c) || - Float.isFloat(c) || - c instanceof Fraction || - (c instanceof Complex && c.re == 0)); - } - - /* string for c*X^i */ - function monomial_toString(c, i) - { - var str1; - if (i == 0) { - str1 = c.toString(); - } else { - if (c == 1) { - str1 = ""; - } else if (c == -1) { - str1 = "-"; - } else { - if (number_need_paren(c)) { - str1 = "(" + c + ")"; - } else { - str1 = String(c); - } - str1 += "*"; - } - str1 += "X"; - if (i != 1) { - str1 += "^" + i; - } - } - return str1; - } - - /* find one complex root of 'p' starting from z at precision eps using - at most max_it iterations. Return null if could not find root. */ - function poly_root_laguerre1(p, z, max_it) - { - var p1, p2, i, z0, z1, z2, d, t0, t1, d1, d2, e, el, zl; - - d = p.deg(); - if (d == 1) { - /* monomial case */ - return -p[0] / p[1]; - } - /* trivial zero */ - if (p[0] == 0) - return 0.0; - - p1 = p.deriv(); - p2 = p1.deriv(); - el = 0.0; - zl = 0.0; - for(i = 0; i < max_it; i++) { - z0 = p.apply(z); - if (z0 == 0) - return z; /* simple exit case */ - - /* Ward stopping criteria */ - e = abs(z - zl); -// print("e", i, e); - if (i >= 2 && e >= el) { - if (abs(zl) < 1e-4) { - if (e < 1e-7) - return zl; - } else { - if (e < abs(zl) * 1e-3) - return zl; - } - } - el = e; - zl = z; - - z1 = p1.apply(z); - z2 = p2.apply(z); - t0 = (d - 1) * z1; - t0 = t0 * t0; - t1 = d * (d - 1) * z0 * z2; - t0 = sqrt(t0 - t1); - d1 = z1 + t0; - d2 = z1 - t0; - if (norm2(d2) > norm2(d1)) - d1 = d2; - if (d1 == 0) - return null; - z = z - d * z0 / d1; - } - return null; - } - - function poly_roots(p) - { - var d, i, roots, j, z, eps; - var start_points = [ 0.1, -1.4, 1.7 ]; - - if (!(p instanceof Polynomial)) - throw TypeError("polynomial expected"); - d = p.deg(); - if (d <= 0) - return []; - eps = 2.0 ^ (-BigFloatEnv.prec); - roots = []; - for(i = 0; i < d; i++) { - /* XXX: should select another start point if error */ - for(j = 0; j < 3; j++) { - z = poly_root_laguerre1(p, start_points[j], 100); - if (z !== null) - break; - } - if (j == 3) - throw RangeError("error in root finding algorithm"); - roots[i] = z; - p = Polynomial.divrem(p, X - z)[0]; - } - return roots; - } - - add_props(Polynomial.prototype, { - trim() { - var a = this, i; - i = a.length; - while (i > 1 && a[i - 1] == 0) - i--; - a.length = i; - return a; - }, - conj() { - var r, i, n, a; - a = this; - n = a.length; - r = []; - for(i = 0; i < n; i++) - r[i] = a[i].conj(); - return Polynomial(r); - }, - inverse() { - return RationalFunction(Polynomial([1]), this); - }, - toString() { - var i, str, str1, c, a = this; - if (a.length == 1) { - return a[0].toString(); - } - str=""; - for(i = a.length - 1; i >= 0; i--) { - c = a[i]; - if (c == 0 || - (c instanceof Mod) && c.res == 0) - continue; - str1 = monomial_toString(c, i); - if (str1[0] != "-") { - if (str != "") - str += "+"; - } - str += str1; - } - return str; - }, - deg() { - if (this.length == 1 && this[0] == 0) - return -Infinity; - else - return this.length - 1; - }, - apply(b) { - var i, n, r, a = this; - n = a.length - 1; - r = a[n]; - while (n > 0) { - n--; - r = r * b + a[n]; - } - return r; - }, - deriv() { - var a = this, n, r, i; - n = a.length; - if (n == 1) { - return Polynomial(0); - } else { - r = []; - for(i = 1; i < n; i++) { - r[i - 1] = i * a[i]; - } - return Polynomial(r); - } - }, - integ() { - var a = this, n, r, i; - n = a.length; - r = [0]; - for(i = 0; i < n; i++) { - r[i + 1] = a[i] / (i + 1); - } - return Polynomial(r); - }, - norm2() { - var a = this, n, r, i; - n = a.length; - r = 0; - for(i = 0; i < n; i++) { - r += a[i].norm2(); - } - return r; - }, - }); - - - function polynomial_add(a, b) { - var tmp, r, i, n1, n2; - a = Polynomial(a); - b = Polynomial(b); - if (a.length < b.length) { - tmp = a; - a = b; - b = tmp; - } - n1 = b.length; - n2 = a.length; - r = []; - for(i = 0; i < n1; i++) - r[i] = a[i] + b[i]; - for(i = n1; i < n2; i++) - r[i] = a[i]; - return Polynomial(r); - } - function polynomial_sub(a, b) { - return polynomial_add(a, -b); - } - function polynomial_mul(a, b) { - var i, j, n1, n2, n, r; - a = Polynomial(a); - b = Polynomial(b); - n1 = a.length; - n2 = b.length; - n = n1 + n2 - 1; - r = []; - for(i = 0; i < n; i++) - r[i] = 0; - for(i = 0; i < n1; i++) { - for(j = 0; j < n2; j++) { - r[i + j] += a[i] * b[j]; - } - } - return Polynomial(r); - } - function polynomial_div_scalar(a, b) { - return a * (1 / b); - } - function polynomial_div(a, b) - { - return RationalFunction(Polynomial(a), - Polynomial(b)); - } - function polynomial_mod(a, b) { - return Polynomial.divrem(a, b)[1]; - } - function polynomial_eq(a, b) { - var n, i; - n = a.length; - if (n != b.length) - return false; - for(i = 0; i < n; i++) { - if (a[i] != b[i]) - return false; - } - return true; - } - - operators_set(Polynomial.prototype, - { - "+": polynomial_add, - "-": polynomial_sub, - "*": polynomial_mul, - "/": polynomial_div, - "**": generic_pow, - "==": polynomial_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - var r, i, n, a; - n = a.length; - r = []; - for(i = 0; i < n; i++) - r[i] = -a[i]; - return Polynomial(r); - }, - }, - { - left: [Number, BigInt, Float, Fraction, Complex, Mod], - "+": polynomial_add, - "-": polynomial_sub, - "*": polynomial_mul, - "/": polynomial_div, - "**": generic_pow, /* XXX: only for integer */ - }, - { - right: [Number, BigInt, Float, Fraction, Complex, Mod], - "+": polynomial_add, - "-": polynomial_sub, - "*": polynomial_mul, - "/": polynomial_div_scalar, - "**": generic_pow, /* XXX: only for integer */ - }); - - add_props(Polynomial, { - divrem(a, b) { - var n1, n2, i, j, q, r, n, c; - if (b.deg() < 0) - throw RangeError("division by zero"); - n1 = a.length; - n2 = b.length; - if (n1 < n2) - return [Polynomial([0]), a]; - r = Array.prototype.dup.call(a); - q = []; - n2--; - n = n1 - n2; - for(i = 0; i < n; i++) - q[i] = 0; - for(i = n - 1; i >= 0; i--) { - c = r[i + n2]; - if (c != 0) { - c = c / b[n2]; - r[i + n2] = 0; - for(j = 0; j < n2; j++) { - r[i + j] -= b[j] * c; - } - q[i] = c; - } - } - return [Polynomial(q), Polynomial(r)]; - }, - gcd(a, b) { - var t; - while (b.deg() >= 0) { - t = Polynomial.divrem(a, b); - a = b; - b = t[1]; - } - /* convert to monic form */ - return a / a[a.length - 1]; - }, - invmod(x, y) { - var q, u, v, a, c, t; - u = x; - v = y; - c = Polynomial([1]); - a = Polynomial([0]); - while (u.deg() >= 0) { - t = Polynomial.divrem(v, u); - q = t[0]; - v = u; - u = t[1]; - t = c; - c = a - q * c; - a = t; - } - /* v = gcd(x, y) */ - if (v.deg() > 0) - throw RangeError("not invertible"); - return Polynomial.divrem(a, y)[1]; - }, - roots(p) { - return poly_roots(p); - } - }); - - /* Polynomial Modulo Q */ - - PolyMod = function PolyMod(a, m) { - var obj, t; - if (new.target) - throw TypeError("not a constructor"); - obj = Object.create(PolyMod.prototype); - if (m instanceof Polynomial) { - if (m.deg() <= 0) - throw RangeError("the modulo cannot have a degree <= 0"); - if (a instanceof RationalFunction) { - return PolyMod(a.num, m) / a.den; - } else { - a = Polynomial(a); - t = Polynomial.divrem(a, m); - a = t[1]; - } - } else { - throw TypeError("invalid types"); - } - obj.res = a; - obj.mod = m; - return obj; - }; - - function polymod_add(a, b) { - if (!(a instanceof PolyMod)) { - return PolyMod(a + b.res, b.mod); - } else if (!(b instanceof PolyMod)) { - return PolyMod(a.res + b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return PolyMod(a.res + b.res, a.mod); - } - } - function polymod_sub(a, b) { - return polymod_add(a, -b); - } - function polymod_mul(a, b) { - if (!(a instanceof PolyMod)) { - return PolyMod(a * b.res, b.mod); - } else if (!(b instanceof PolyMod)) { - return PolyMod(a.res * b, a.mod); - } else { - if (a.mod != b.mod) - throw TypeError("different modulo for binary operator"); - return PolyMod(a.res * b.res, a.mod); - } - } - function polymod_div(a, b) { - if (!(b instanceof PolyMod)) - b = PolyMod(b, a.mod); - return polymod_mul(a, b.inverse()); - } - function polymod_eq(a, b) { - return (a.mod == b.mod && a.res == b.res); - } - - operators_set(PolyMod.prototype, - { - "+": polymod_add, - "-": polymod_sub, - "*": polymod_mul, - "/": polymod_div, - "**": generic_pow, - "==": polymod_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - return PolyMod(-a.res, a.mod); - }, - }, - { - left: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - right: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - "+": polymod_add, - "-": polymod_sub, - "*": polymod_mul, - "/": polymod_div, - "**": generic_pow, /* XXX: only for integer */ - }); - - add_props(PolyMod.prototype, { - inverse() { - var a = this, m = a.mod; - if (m instanceof Polynomial) { - return PolyMod(Polynomial.invmod(a.res, m), m); - } else { - throw TypeError("unsupported type"); - } - }, - toString() { - return "PolyMod(" + this.res + "," + this.mod + ")"; - }, - }); - - /* Rational function */ - - RationalFunction = function RationalFunction(a, b) - { - var t, r, d, obj; - if (new.target) - throw TypeError("not a constructor"); - if (!(a instanceof Polynomial) || - !(b instanceof Polynomial)) - throw TypeError("polynomial expected"); - t = Polynomial.divrem(a, b); - r = t[1]; - if (r.deg() < 0) - return t[0]; /* no need for a fraction */ - d = Polynomial.gcd(b, r); - if (d.deg() > 0) { - a = Polynomial.divrem(a, d)[0]; - b = Polynomial.divrem(b, d)[0]; - } - obj = Object.create(RationalFunction.prototype); - obj.num = a; - obj.den = b; - return obj; - } - - add_props(RationalFunction.prototype, { - inverse() { - return RationalFunction(this.den, this.num); - }, - conj() { - return RationalFunction(this.num.conj(), this.den.conj()); - }, - toString() { - var str; - if (this.num.deg() <= 0 && - !number_need_paren(this.num[0])) - str = this.num.toString(); - else - str = "(" + this.num.toString() + ")"; - str += "/(" + this.den.toString() + ")" - return str; - }, - apply(b) { - return this.num.apply(b) / this.den.apply(b); - }, - deriv() { - var n = this.num, d = this.den; - return RationalFunction(n.deriv() * d - n * d.deriv(), d * d); - }, - }); - - function ratfunc_add(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - return RationalFunction(a.num * b.den + a.den * b.num, a.den * b.den); - } - function ratfunc_sub(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - return RationalFunction(a.num * b.den - a.den * b.num, a.den * b.den); - } - function ratfunc_mul(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - return RationalFunction(a.num * b.num, a.den * b.den); - } - function ratfunc_div(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - return RationalFunction(a.num * b.den, a.den * b.num); - } - function ratfunc_eq(a, b) { - a = RationalFunction.toRationalFunction(a); - b = RationalFunction.toRationalFunction(b); - /* we assume the fractions are normalized */ - return (a.num == b.num && a.den == b.den); - } - - operators_set(RationalFunction.prototype, - { - "+": ratfunc_add, - "-": ratfunc_sub, - "*": ratfunc_mul, - "/": ratfunc_div, - "**": generic_pow, - "==": ratfunc_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - return RationalFunction(-this.num, this.den); - }, - }, - { - left: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - right: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - "+": ratfunc_add, - "-": ratfunc_sub, - "*": ratfunc_mul, - "/": ratfunc_div, - "**": generic_pow, /* should only be used with integers */ - }); - - add_props(RationalFunction, { - /* This function always return a RationalFunction object even - if it could simplified to a polynomial, so it is not - equivalent to RationalFunction(a) */ - toRationalFunction(a) { - var obj; - if (a instanceof RationalFunction) { - return a; - } else { - obj = Object.create(RationalFunction.prototype); - obj.num = Polynomial(a); - obj.den = Polynomial(1); - return obj; - } - }, - }); - - /* Power series */ - - /* 'a' is an array */ - function get_emin(a) { - var i, n; - n = a.length; - for(i = 0; i < n; i++) { - if (a[i] != 0) - return i; - } - return n; - }; - - function series_is_scalar_or_polynomial(a) - { - return polynomial_is_scalar(a) || - (a instanceof Polynomial); - } - - /* n is the maximum number of terms if 'a' is not a serie */ - Series = function Series(a, n) { - var emin, r, i; - - if (a instanceof Series) { - return a; - } else if (series_is_scalar_or_polynomial(a)) { - if (n <= 0) { - /* XXX: should still use the polynomial degree */ - return Series.zero(0, 0); - } else { - a = Polynomial(a); - emin = get_emin(a); - r = Series.zero(n, emin); - n = Math.min(a.length - emin, n); - for(i = 0; i < n; i++) - r[i] = a[i + emin]; - return r; - } - } else if (a instanceof RationalFunction) { - return Series(a.num, n) / a.den; - } else { - throw TypeError("invalid type"); - } - }; - - function series_add(v1, v2) { - var tmp, d, emin, n, r, i, j, v2_emin, c1, c2; - if (!(v1 instanceof Series)) { - tmp = v1; - v1 = v2; - v2 = tmp; - } - d = v1.emin + v1.length; - if (series_is_scalar_or_polynomial(v2)) { - v2 = Polynomial(v2); - if (d <= 0) - return v1; - v2_emin = 0; - } else if (v2 instanceof RationalFunction) { - /* compute the emin of the rational fonction */ - i = get_emin(v2.num) - get_emin(v2.den); - if (d <= i) - return v1; - /* compute the serie with the required terms */ - v2 = Series(v2, d - i); - v2_emin = v2.emin; - } else { - v2_emin = v2.emin; - d = Math.min(d, v2_emin + v2.length); - } - emin = Math.min(v1.emin, v2_emin); - n = d - emin; - r = Series.zero(n, emin); - /* XXX: slow */ - for(i = emin; i < d; i++) { - j = i - v1.emin; - if (j >= 0 && j < v1.length) - c1 = v1[j]; - else - c1 = 0; - j = i - v2_emin; - if (j >= 0 && j < v2.length) - c2 = v2[j]; - else - c2 = 0; - r[i - emin] = c1 + c2; - } - return r.trim(); - } - function series_sub(a, b) { - return series_add(a, -b); - } - function series_mul(v1, v2) { - var n, i, j, r, n, emin, n1, n2, k; - if (!(v1 instanceof Series)) - v1 = Series(v1, v2.length); - else if (!(v2 instanceof Series)) - v2 = Series(v2, v1.length); - emin = v1.emin + v2.emin; - n = Math.min(v1.length, v2.length); - n1 = v1.length; - n2 = v2.length; - r = Series.zero(n, emin); - for(i = 0; i < n1; i++) { - k = Math.min(n2, n - i); - for(j = 0; j < k; j++) { - r[i + j] += v1[i] * v2[j]; - } - } - return r.trim(); - } - function series_div(v1, v2) { - if (!(v2 instanceof Series)) - v2 = Series(v2, v1.length); - return series_mul(v1, v2.inverse()); - } - function series_pow(a, b) { - if (Integer.isInteger(b)) { - return generic_pow(a, b); - } else { - if (!(a instanceof Series)) - a = Series(a, b.length); - return exp(log(a) * b); - } - } - function series_eq(a, b) { - var n, i; - if (a.emin != b.emin) - return false; - n = a.length; - if (n != b.length) - return false; - for(i = 0; i < n; i++) { - if (a[i] != b[i]) - return false; - } - return true; - } - - operators_set(Series.prototype, - { - "+": series_add, - "-": series_sub, - "*": series_mul, - "/": series_div, - "**": series_pow, - "==": series_eq, - "pos"(a) { - return a; - }, - "neg"(a) { - var obj, n, i; - n = a.length; - obj = Series.zero(a.length, a.emin); - for(i = 0; i < n; i++) { - obj[i] = -a[i]; - } - return obj; - }, - }, - { - left: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - right: [Number, BigInt, Float, Fraction, Complex, Mod, Polynomial], - "+": series_add, - "-": series_sub, - "*": series_mul, - "/": series_div, - "**": series_pow, - }); - - add_props(Series.prototype, { - conj() { - var obj, n, i; - n = this.length; - obj = Series.zero(this.length, this.emin); - for(i = 0; i < n; i++) { - obj[i] = this[i].conj(); - } - return obj; - }, - inverse() { - var r, n, i, j, sum, v1 = this; - n = v1.length; - if (n == 0) - throw RangeError("division by zero"); - r = Series.zero(n, -v1.emin); - r[0] = 1 / v1[0]; - for(i = 1; i < n; i++) { - sum = 0; - for(j = 1; j <= i; j++) { - sum += v1[j] * r[i - j]; - } - r[i] = -sum * r[0]; - } - return r; - }, - /* remove leading zero terms */ - trim() { - var i, j, n, r, v1 = this; - n = v1.length; - i = 0; - while (i < n && v1[i] == 0) - i++; - if (i == 0) - return v1; - for(j = i; j < n; j++) - v1[j - i] = v1[j]; - v1.length = n - i; - v1.__proto__.emin += i; - return v1; - }, - toString() { - var i, j, str, str1, c, a = this, emin, n; - str=""; - emin = this.emin; - n = this.length; - for(j = 0; j < n; j++) { - i = j + emin; - c = a[j]; - if (c != 0) { - str1 = monomial_toString(c, i); - if (str1[0] != "-") { - if (str != "") - str += "+"; - } - str += str1; - } - } - if (str != "") - str += "+"; - str += "O(" + monomial_toString(1, n + emin) + ")"; - return str; - }, - apply(b) { - var i, n, r, a = this; - n = a.length; - if (n == 0) - return 0; - r = a[--n]; - while (n > 0) { - n--; - r = r * b + a[n]; - } - if (a.emin != 0) - r *= b ^ a.emin; - return r; - }, - deriv() { - var a = this, n = a.length, emin = a.emin, r, i, j; - if (n == 0 && emin == 0) { - return Series.zero(0, 0); - } else { - r = Series.zero(n, emin - 1); - for(i = 0; i < n; i++) { - j = emin + i; - if (j == 0) - r[i] = 0; - else - r[i] = j * a[i]; - } - return r.trim(); - } - }, - integ() { - var a = this, n = a.length, emin = a.emin, i, j, r; - r = Series.zero(n, emin + 1); - for(i = 0; i < n; i++) { - j = emin + i; - if (j == -1) { - if (a[i] != 0) - throw RangeError("cannot represent integ(1/X)"); - } else { - r[i] = a[i] / (j + 1); - } - } - return r.trim(); - }, - exp() { - var c, i, r, n, a = this; - if (a.emin < 0) - throw RangeError("negative exponent in exp"); - n = a.emin + a.length; - if (a.emin > 0 || a[0] == 0) { - c = 1; - } else { - c = global.exp(a[0]); - a -= a[0]; - } - r = Series.zero(n, 0); - for(i = 0; i < n; i++) { - r[i] = c / fact(i); - } - return r.apply(a); - }, - log() { - var a = this, r; - if (a.emin != 0) - throw RangeError("log argument must have a non zero constant term"); - r = integ(deriv(a) / a); - /* add the constant term */ - r += global.log(a[0]); - return r; - }, - }); - - add_props(Series, { - /* new series of length n and first exponent emin */ - zero(n, emin) { - var r, i, obj; - - r = []; - for(i = 0; i < n; i++) - r[i] = 0; - /* we return an array and store emin in its prototype */ - obj = Object.create(Series.prototype); - obj.emin = emin; - Object.setPrototypeOf(r, obj); - return r; - }, - O(a) { - function ErrorO() { - return TypeError("invalid O() argument"); - } - var n; - if (series_is_scalar_or_polynomial(a)) { - a = Polynomial(a); - n = a.deg(); - if (n < 0) - throw ErrorO(); - } else if (a instanceof RationalFunction) { - if (a.num.deg() != 0) - throw ErrorO(); - n = a.den.deg(); - if (n < 0) - throw ErrorO(); - n = -n; - } else - throw ErrorO(); - return Series.zero(0, n); - }, - }); - - /* Array (Matrix) */ - - Matrix = function Matrix(h, w) { - var i, j, r, rl; - if (typeof w === "undefined") - w = h; - r = []; - for(i = 0; i < h; i++) { - rl = []; - for(j = 0; j < w; j++) - rl[j] = 0; - r[i] = rl; - } - return r; - }; - - add_props(Matrix, { - idn(n) { - var r, i; - r = Matrix(n, n); - for(i = 0; i < n; i++) - r[i][i] = 1; - return r; - }, - diag(a) { - var r, i, n; - n = a.length; - r = Matrix(n, n); - for(i = 0; i < n; i++) - r[i][i] = a[i]; - return r; - }, - hilbert(n) { - var i, j, r; - r = Matrix(n); - for(i = 0; i < n; i++) { - for(j = 0; j < n; j++) { - r[i][j] = 1 / (1 + i + j); - } - } - return r; - }, - trans(a) { - var h, w, r, i, j; - if (!Array.isArray(a)) - throw TypeError("matrix expected"); - h = a.length; - if (!Array.isArray(a[0])) { - w = 1; - r = Matrix(w, h); - for(i = 0; i < h; i++) { - r[0][i] = a[i]; - } - } else { - w = a[0].length; - r = Matrix(w, h); - for(i = 0; i < h; i++) { - for(j = 0; j < w; j++) { - r[j][i] = a[i][j]; - } - } - } - return r; - }, - check_square(a) { - var a, n; - if (!Array.isArray(a)) - throw TypeError("array expected"); - n = a.length; - if (!Array.isArray(a[0]) || n != a[0].length) - throw TypeError("square matrix expected"); - return n; - }, - trace(a) { - var n, r, i; - n = Matrix.check_square(a); - r = a[0][0]; - for(i = 1; i < n; i++) { - r += a[i][i]; - } - return r; - }, - charpoly(a) { - var n, p, c, i, j, coef; - n = Matrix.check_square(a); - p = []; - for(i = 0; i < n + 1; i++) - p[i] = 0; - p[n] = 1; - c = Matrix.idn(n); - for(i = 0; i < n; i++) { - c = c * a; - coef = -trace(c) / (i + 1); - p[n - i - 1] = coef; - for(j = 0; j < n; j++) - c[j][j] += coef; - } - return Polynomial(p); - }, - eigenvals(a) { - return Polynomial.roots(Matrix.charpoly(a)); - }, - det(a) { - var n, i, j, k, s, src, v, c; - - n = Matrix.check_square(a); - s = 1; - src = a.dup(); - for(i=0;iclass_array[JS_CLASS_C_FUNCTION].call = js_call_c_function; rt->class_array[JS_CLASS_C_FUNCTION_DATA].call = js_c_function_data_call; rt->class_array[JS_CLASS_BOUND_FUNCTION].call = js_call_bound_function; +#ifdef JS_PROMISE rt->class_array[JS_CLASS_GENERATOR_FUNCTION].call = js_generator_function_call; +#endif if (init_shape_hash(rt)) goto fail; @@ -2158,13 +2173,13 @@ JSContext *JS_NewContext(JSRuntime *rt) JS_AddIntrinsicBaseObjects(ctx); JS_AddIntrinsicDate(ctx); JS_AddIntrinsicEval(ctx); - JS_AddIntrinsicStringNormalize(ctx); +// JS_AddIntrinsicStringNormalize(ctx); JS_AddIntrinsicRegExp(ctx); JS_AddIntrinsicJSON(ctx); - JS_AddIntrinsicProxy(ctx); - JS_AddIntrinsicMapSet(ctx); - JS_AddIntrinsicTypedArrays(ctx); - JS_AddIntrinsicPromise(ctx); +// JS_AddIntrinsicProxy(ctx); +// JS_AddIntrinsicMapSet(ctx); +// JS_AddIntrinsicTypedArrays(ctx); +// JS_AddIntrinsicPromise(ctx); #ifdef CONFIG_BIGNUM JS_AddIntrinsicBigInt(ctx); #endif @@ -5417,9 +5432,11 @@ static void free_object(JSRuntime *rt, JSObject *p) p->shape = NULL; p->prop = NULL; +#ifdef JS_MAP if (unlikely(p->first_weak_ref)) { reset_weak_ref(rt, p); } +#endif finalizer = rt->class_array[p->class_id].finalizer; if (finalizer) @@ -5647,6 +5664,7 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, JS_MarkValue(rt, *var_ref->pvalue, mark_func); } break; +#ifdef JS_PROMISE case JS_GC_OBJ_TYPE_ASYNC_FUNCTION: { JSAsyncFunctionData *s = (JSAsyncFunctionData *)gp; @@ -5656,6 +5674,7 @@ static void mark_children(JSRuntime *rt, JSGCObjectHeader *gp, JS_MarkValue(rt, s->resolving_funcs[1], mark_func); } break; +#endif case JS_GC_OBJ_TYPE_SHAPE: { JSShape *sh = (JSShape *)gp; @@ -6825,8 +6844,10 @@ static int JS_SetPrototypeInternal(JSContext *ctx, JSValueConst obj, if (throw_flag && JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT) return TRUE; +#ifdef JS_PROXY if (unlikely(p->class_id == JS_CLASS_PROXY)) return js_proxy_setPrototypeOf(ctx, obj, proto_val, throw_flag); +#endif sh = p->shape; if (sh->proto == proto) return TRUE; @@ -6916,6 +6937,8 @@ JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj) if (JS_VALUE_GET_TAG(obj) == JS_TAG_OBJECT) { JSObject *p; p = JS_VALUE_GET_OBJ(obj); + +#ifdef JS_PROXY if (unlikely(p->class_id == JS_CLASS_PROXY)) { val = js_proxy_getPrototypeOf(ctx, obj); } else { @@ -6925,6 +6948,13 @@ JSValue JS_GetPrototype(JSContext *ctx, JSValueConst obj) else val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); } +#else + p = p->shape->proto; + if (!p) + val = JS_NULL; + else + val = JS_DupValue(ctx, JS_MKPTR(JS_TAG_OBJECT, p)); +#endif } else { val = JS_DupValue(ctx, JS_GetPrototypePrimitive(ctx, obj)); } @@ -7746,9 +7776,11 @@ int JS_IsExtensible(JSContext *ctx, JSValueConst obj) if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) return FALSE; p = JS_VALUE_GET_OBJ(obj); +#ifdef JS_PROXY if (unlikely(p->class_id == JS_CLASS_PROXY)) return js_proxy_isExtensible(ctx, obj); else +#endif return p->extensible; } @@ -7760,8 +7792,10 @@ int JS_PreventExtensions(JSContext *ctx, JSValueConst obj) if (unlikely(JS_VALUE_GET_TAG(obj) != JS_TAG_OBJECT)) return FALSE; p = JS_VALUE_GET_OBJ(obj); +#ifdef JS_PROXY if (unlikely(p->class_id == JS_CLASS_PROXY)) return js_proxy_preventExtensions(ctx, obj); +#endif p->extensible = FALSE; return TRUE; } @@ -11971,9 +12005,11 @@ int JS_IsArray(JSContext *ctx, JSValueConst val) JSObject *p; if (JS_VALUE_GET_TAG(val) == JS_TAG_OBJECT) { p = JS_VALUE_GET_OBJ(val); +#ifdef JS_PROXY if (unlikely(p->class_id == JS_CLASS_PROXY)) return js_proxy_isArray(ctx, val); else +#endif return p->class_id == JS_CLASS_ARRAY; } else { return FALSE; @@ -15268,6 +15304,7 @@ static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async) { JSValue method, ret, sync_iter; +#ifdef JS_PROMISE if (is_async) { method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_asyncIterator); if (JS_IsException(method)) @@ -15284,7 +15321,9 @@ static JSValue JS_GetIterator(JSContext *ctx, JSValueConst obj, BOOL is_async) JS_FreeValue(ctx, sync_iter); return ret; } - } else { + } else +#endif + { method = JS_GetProperty(ctx, obj, JS_ATOM_Symbol_iterator); if (JS_IsException(method)) return method; @@ -18749,6 +18788,7 @@ static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj) realm = b->realm; } break; +#ifdef JS_PROXY case JS_CLASS_PROXY: { JSProxyData *s = p->u.opaque; @@ -18762,6 +18802,7 @@ static JSContext *JS_GetFunctionRealm(JSContext *ctx, JSValueConst func_obj) } } break; +#endif case JS_CLASS_BOUND_FUNCTION: { JSBoundFunction *bf = p->u.bound_function; @@ -18885,6 +18926,7 @@ static JSValue JS_InvokeFree(JSContext *ctx, JSValue this_val, JSAtom atom, } /* JSAsyncFunctionState (used by generator and async functions) */ +#ifdef JS_PROMISE static __exception int async_func_init(JSContext *ctx, JSAsyncFunctionState *s, JSValueConst func_obj, JSValueConst this_obj, int argc, JSValueConst *argv) @@ -19765,6 +19807,7 @@ static JSValue js_async_generator_function_call(JSContext *ctx, JSValueConst fun js_async_generator_free(ctx->rt, s); return JS_EXCEPTION; } +#endif /* JS parser */ @@ -28267,12 +28310,14 @@ static JSValue js_dynamic_import(JSContext *ctx, JSValueConst specifier) JS_FreeAtom(ctx, basename); if (JS_IsException(basename_val)) return basename_val; - + +#ifdef JS_PROMISE promise = JS_NewPromiseCapability(ctx, resolving_funcs); if (JS_IsException(promise)) { JS_FreeValue(ctx, basename_val); return promise; } +#endif args[0] = resolving_funcs[0]; args[1] = resolving_funcs[1]; @@ -41712,14 +41757,18 @@ static const JSCFunctionListEntry js_string_proto_normalize[] = { }; #endif + void JS_AddIntrinsicStringNormalize(JSContext *ctx) { +#ifdef JS_STRINGNORMALIZE #ifdef CONFIG_ALL_UNICODE JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_STRING], js_string_proto_normalize, countof(js_string_proto_normalize)); #endif +#endif } + /* Math */ /* precondition: a and b are not NaN */ @@ -44412,6 +44461,7 @@ static const JSCFunctionListEntry js_reflect_obj[] = { }; /* Proxy */ +#ifdef JS_PROXY static void js_proxy_finalizer(JSRuntime *rt, JSValue val) { @@ -45364,6 +45414,8 @@ void JS_AddIntrinsicProxy(JSContext *ctx) obj1, JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE); } +#endif + /* Symbol */ static JSValue js_symbol_constructor(JSContext *ctx, JSValueConst new_target, @@ -45476,6 +45528,7 @@ static const JSCFunctionListEntry js_symbol_funcs[] = { }; /* Set/Map/WeakSet/WeakMap */ +#ifdef JS_MAP typedef struct JSMapRecord { int ref_count; /* used during enumeration to avoid freeing the record */ @@ -46223,6 +46276,7 @@ static const uint8_t js_map_proto_funcs_count[6] = { countof(js_set_iterator_proto_funcs), }; + void JS_AddIntrinsicMapSet(JSContext *ctx) { int i; @@ -46253,8 +46307,10 @@ void JS_AddIntrinsicMapSet(JSContext *ctx) js_map_proto_funcs_count[i + 4]); } } +#endif /* Generator */ +#ifdef JS_PROMISE static const JSCFunctionListEntry js_generator_function_proto_funcs[] = { JS_PROP_STRING_DEF("[Symbol.toStringTag]", "GeneratorFunction", JS_PROP_CONFIGURABLE), }; @@ -46268,6 +46324,7 @@ static const JSCFunctionListEntry js_generator_proto_funcs[] = { /* Promise */ + typedef enum JSPromiseStateEnum { JS_PROMISE_PENDING, JS_PROMISE_FULFILLED, @@ -47492,6 +47549,7 @@ static JSClassShortDef const js_async_class_def[] = { { JS_ATOM_AsyncGenerator, js_async_generator_finalizer, js_async_generator_mark }, /* JS_CLASS_ASYNC_GENERATOR */ }; + void JS_AddIntrinsicPromise(JSContext *ctx) { JSRuntime *rt = ctx->rt; @@ -47576,7 +47634,7 @@ void JS_AddIntrinsicPromise(JSContext *ctx) 0, JS_PROP_CONFIGURABLE); JS_FreeValue(ctx, obj1); } - +#endif /* URI handling */ static int string_get_hex(JSString *p, int k, int n) { @@ -51081,6 +51139,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) } /* ES6 Generator */ +#ifdef JS_PROMISE ctx->class_proto[JS_CLASS_GENERATOR] = JS_NewObjectProto(ctx, ctx->iterator_proto); JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_GENERATOR], js_generator_proto_funcs, @@ -51100,7 +51159,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) JS_SetConstructor2(ctx, obj1, ctx->class_proto[JS_CLASS_GENERATOR_FUNCTION], 0, JS_PROP_CONFIGURABLE); JS_FreeValue(ctx, obj1); - +#endif /* global properties */ ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1); JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval, @@ -51113,7 +51172,7 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx) } /* Typed Arrays */ - +#ifdef JS_TYPEDARRAY static uint8_t const typed_array_size_log2[JS_TYPED_ARRAY_COUNT] = { 0, 0, 0, 1, 1, 2, 2, #ifdef CONFIG_BIGNUM @@ -53479,7 +53538,7 @@ static const JSCFunctionListEntry js_dataview_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("setFloat64", 2, js_dataview_setValue, JS_CLASS_FLOAT64_ARRAY ), JS_PROP_STRING_DEF("[Symbol.toStringTag]", "DataView", JS_PROP_CONFIGURABLE ), }; - +#endif /* Atomics */ #ifdef CONFIG_ATOMICS @@ -53972,8 +54031,11 @@ void JS_AddIntrinsicAtomics(JSContext *ctx) JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_atomics_obj, countof(js_atomics_obj)); } -#endif /* CONFIG_ATOMICS */ +#endif +/* CONFIG_ATOMICS */ + +#ifdef JS_TYPEDARRAY void JS_AddIntrinsicTypedArrays(JSContext *ctx) { JSValue typed_array_base_proto, typed_array_base_func; @@ -54059,3 +54121,4 @@ void JS_AddIntrinsicTypedArrays(JSContext *ctx) JS_AddIntrinsicAtomics(ctx); #endif } +#endif diff --git a/quickjs/quickjs.h b/quickjs/quickjs.h index d4a5cd3..0ad9d16 100644 --- a/quickjs/quickjs.h +++ b/quickjs/quickjs.h @@ -366,7 +366,7 @@ void JS_AddIntrinsicStringNormalize(JSContext *ctx); void JS_AddIntrinsicRegExpCompiler(JSContext *ctx); void JS_AddIntrinsicRegExp(JSContext *ctx); void JS_AddIntrinsicJSON(JSContext *ctx); -void JS_AddIntrinsicProxy(JSContext *ctx); +//void JS_AddIntrinsicProxy(JSContext *ctx); void JS_AddIntrinsicMapSet(JSContext *ctx); void JS_AddIntrinsicTypedArrays(JSContext *ctx); void JS_AddIntrinsicPromise(JSContext *ctx); diff --git a/quickjs/repl.js b/quickjs/repl.js deleted file mode 100644 index 484269e..0000000 --- a/quickjs/repl.js +++ /dev/null @@ -1,1566 +0,0 @@ -/* - * QuickJS Read Eval Print Loop - * - * Copyright (c) 2017-2020 Fabrice Bellard - * Copyright (c) 2017-2020 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -"use strip"; - -import * as std from "std"; -import * as os from "os"; - -(function(g) { - /* add 'os' and 'std' bindings */ - g.os = os; - g.std = std; - - /* close global objects */ - var Object = g.Object; - var String = g.String; - var Array = g.Array; - var Date = g.Date; - var Math = g.Math; - var isFinite = g.isFinite; - var parseFloat = g.parseFloat; - - /* XXX: use preprocessor ? */ - var config_numcalc = (typeof os.open === "undefined"); - var has_jscalc = (typeof Fraction === "function"); - var has_bignum = (typeof BigFloat === "function"); - - var colors = { - none: "\x1b[0m", - black: "\x1b[30m", - red: "\x1b[31m", - green: "\x1b[32m", - yellow: "\x1b[33m", - blue: "\x1b[34m", - magenta: "\x1b[35m", - cyan: "\x1b[36m", - white: "\x1b[37m", - gray: "\x1b[30;1m", - grey: "\x1b[30;1m", - bright_red: "\x1b[31;1m", - bright_green: "\x1b[32;1m", - bright_yellow: "\x1b[33;1m", - bright_blue: "\x1b[34;1m", - bright_magenta: "\x1b[35;1m", - bright_cyan: "\x1b[36;1m", - bright_white: "\x1b[37;1m", - }; - - var styles; - if (config_numcalc) { - styles = { - 'default': 'black', - 'comment': 'white', - 'string': 'green', - 'regex': 'cyan', - 'number': 'green', - 'keyword': 'blue', - 'function': 'gray', - 'type': 'bright_magenta', - 'identifier': 'yellow', - 'error': 'bright_red', - 'result': 'black', - 'error_msg': 'bright_red', - }; - } else { - styles = { - 'default': 'bright_green', - 'comment': 'white', - 'string': 'bright_cyan', - 'regex': 'cyan', - 'number': 'green', - 'keyword': 'bright_white', - 'function': 'bright_yellow', - 'type': 'bright_magenta', - 'identifier': 'bright_green', - 'error': 'red', - 'result': 'bright_white', - 'error_msg': 'bright_red', - }; - } - - var history = []; - var clip_board = ""; - var prec; - var expBits; - var log2_10; - - var pstate = ""; - var prompt = ""; - var plen = 0; - var ps1; - if (config_numcalc) - ps1 = "> "; - else - ps1 = "qjs > "; - var ps2 = " ... "; - var utf8 = true; - var show_time = false; - var show_colors = true; - var eval_time = 0; - - var mexpr = ""; - var level = 0; - var cmd = ""; - var cursor_pos = 0; - var last_cmd = ""; - var last_cursor_pos = 0; - var history_index; - var this_fun, last_fun; - var quote_flag = false; - - var utf8_state = 0; - var utf8_val = 0; - - var term_fd; - var term_read_buf; - var term_width; - /* current X position of the cursor in the terminal */ - var term_cursor_x = 0; - - function termInit() { - var tab; - term_fd = std.in.fileno(); - - /* get the terminal size */ - term_width = 80; - if (os.isatty(term_fd)) { - if (os.ttyGetWinSize) { - tab = os.ttyGetWinSize(term_fd); - if (tab) - term_width = tab[0]; - } - if (os.ttySetRaw) { - /* set the TTY to raw mode */ - os.ttySetRaw(term_fd); - } - } - - /* install a Ctrl-C signal handler */ - os.signal(os.SIGINT, sigint_handler); - - /* install a handler to read stdin */ - term_read_buf = new Uint8Array(64); - os.setReadHandler(term_fd, term_read_handler); - } - - function sigint_handler() { - /* send Ctrl-C to readline */ - handle_byte(3); - } - - function term_read_handler() { - var l, i; - l = os.read(term_fd, term_read_buf.buffer, 0, term_read_buf.length); - for(i = 0; i < l; i++) - handle_byte(term_read_buf[i]); - } - - function handle_byte(c) { - if (!utf8) { - handle_char(c); - } else if (utf8_state !== 0 && (c >= 0x80 && c < 0xc0)) { - utf8_val = (utf8_val << 6) | (c & 0x3F); - utf8_state--; - if (utf8_state === 0) { - handle_char(utf8_val); - } - } else if (c >= 0xc0 && c < 0xf8) { - utf8_state = 1 + (c >= 0xe0) + (c >= 0xf0); - utf8_val = c & ((1 << (6 - utf8_state)) - 1); - } else { - utf8_state = 0; - handle_char(c); - } - } - - function is_alpha(c) { - return typeof c === "string" && - ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')); - } - - function is_digit(c) { - return typeof c === "string" && (c >= '0' && c <= '9'); - } - - function is_word(c) { - return typeof c === "string" && - (is_alpha(c) || is_digit(c) || c == '_' || c == '$'); - } - - function ucs_length(str) { - var len, c, i, str_len = str.length; - len = 0; - /* we never count the trailing surrogate to have the - following property: ucs_length(str) = - ucs_length(str.substring(0, a)) + ucs_length(str.substring(a, - str.length)) for 0 <= a <= str.length */ - for(i = 0; i < str_len; i++) { - c = str.charCodeAt(i); - if (c < 0xdc00 || c >= 0xe000) - len++; - } - return len; - } - - function is_trailing_surrogate(c) { - var d; - if (typeof c !== "string") - return false; - d = c.codePointAt(0); /* can be NaN if empty string */ - return d >= 0xdc00 && d < 0xe000; - } - - function is_balanced(a, b) { - switch (a + b) { - case "()": - case "[]": - case "{}": - return true; - } - return false; - } - - function print_color_text(str, start, style_names) { - var i, j; - for (j = start; j < str.length;) { - var style = style_names[i = j]; - while (++j < str.length && style_names[j] == style) - continue; - std.puts(colors[styles[style] || 'default']); - std.puts(str.substring(i, j)); - std.puts(colors['none']); - } - } - - function print_csi(n, code) { - std.puts("\x1b[" + ((n != 1) ? n : "") + code); - } - - /* XXX: handle double-width characters */ - function move_cursor(delta) { - var i, l; - if (delta > 0) { - while (delta != 0) { - if (term_cursor_x == (term_width - 1)) { - std.puts("\n"); /* translated to CRLF */ - term_cursor_x = 0; - delta--; - } else { - l = Math.min(term_width - 1 - term_cursor_x, delta); - print_csi(l, "C"); /* right */ - delta -= l; - term_cursor_x += l; - } - } - } else { - delta = -delta; - while (delta != 0) { - if (term_cursor_x == 0) { - print_csi(1, "A"); /* up */ - print_csi(term_width - 1, "C"); /* right */ - delta--; - term_cursor_x = term_width - 1; - } else { - l = Math.min(delta, term_cursor_x); - print_csi(l, "D"); /* left */ - delta -= l; - term_cursor_x -= l; - } - } - } - } - - function update() { - var i, cmd_len; - /* cursor_pos is the position in 16 bit characters inside the - UTF-16 string 'cmd' */ - if (cmd != last_cmd) { - if (!show_colors && last_cmd.substring(0, last_cursor_pos) == cmd.substring(0, last_cursor_pos)) { - /* optimize common case */ - std.puts(cmd.substring(last_cursor_pos)); - } else { - /* goto the start of the line */ - move_cursor(-ucs_length(last_cmd.substring(0, last_cursor_pos))); - if (show_colors) { - var str = mexpr ? mexpr + '\n' + cmd : cmd; - var start = str.length - cmd.length; - var colorstate = colorize_js(str); - print_color_text(str, start, colorstate[2]); - } else { - std.puts(cmd); - } - } - term_cursor_x = (term_cursor_x + ucs_length(cmd)) % term_width; - if (term_cursor_x == 0) { - /* show the cursor on the next line */ - std.puts(" \x08"); - } - /* remove the trailing characters */ - std.puts("\x1b[J"); - last_cmd = cmd; - last_cursor_pos = cmd.length; - } - if (cursor_pos > last_cursor_pos) { - move_cursor(ucs_length(cmd.substring(last_cursor_pos, cursor_pos))); - } else if (cursor_pos < last_cursor_pos) { - move_cursor(-ucs_length(cmd.substring(cursor_pos, last_cursor_pos))); - } - last_cursor_pos = cursor_pos; - std.out.flush(); - } - - /* editing commands */ - function insert(str) { - if (str) { - cmd = cmd.substring(0, cursor_pos) + str + cmd.substring(cursor_pos); - cursor_pos += str.length; - } - } - - function quoted_insert() { - quote_flag = true; - } - - function abort() { - cmd = ""; - cursor_pos = 0; - return -2; - } - - function alert() { - } - - function beginning_of_line() { - cursor_pos = 0; - } - - function end_of_line() { - cursor_pos = cmd.length; - } - - function forward_char() { - if (cursor_pos < cmd.length) { - cursor_pos++; - while (is_trailing_surrogate(cmd.charAt(cursor_pos))) - cursor_pos++; - } - } - - function backward_char() { - if (cursor_pos > 0) { - cursor_pos--; - while (is_trailing_surrogate(cmd.charAt(cursor_pos))) - cursor_pos--; - } - } - - function skip_word_forward(pos) { - while (pos < cmd.length && !is_word(cmd.charAt(pos))) - pos++; - while (pos < cmd.length && is_word(cmd.charAt(pos))) - pos++; - return pos; - } - - function skip_word_backward(pos) { - while (pos > 0 && !is_word(cmd.charAt(pos - 1))) - pos--; - while (pos > 0 && is_word(cmd.charAt(pos - 1))) - pos--; - return pos; - } - - function forward_word() { - cursor_pos = skip_word_forward(cursor_pos); - } - - function backward_word() { - cursor_pos = skip_word_backward(cursor_pos); - } - - function accept_line() { - std.puts("\n"); - history_add(cmd); - return -1; - } - - function history_add(str) { - if (str) { - history.push(str); - } - history_index = history.length; - } - - function previous_history() { - if (history_index > 0) { - if (history_index == history.length) { - history.push(cmd); - } - history_index--; - cmd = history[history_index]; - cursor_pos = cmd.length; - } - } - - function next_history() { - if (history_index < history.length - 1) { - history_index++; - cmd = history[history_index]; - cursor_pos = cmd.length; - } - } - - function history_search(dir) { - var pos = cursor_pos; - for (var i = 1; i <= history.length; i++) { - var index = (history.length + i * dir + history_index) % history.length; - if (history[index].substring(0, pos) == cmd.substring(0, pos)) { - history_index = index; - cmd = history[index]; - return; - } - } - } - - function history_search_backward() { - return history_search(-1); - } - - function history_search_forward() { - return history_search(1); - } - - function delete_char_dir(dir) { - var start, end; - - start = cursor_pos; - if (dir < 0) { - start--; - while (is_trailing_surrogate(cmd.charAt(start))) - start--; - } - end = start + 1; - while (is_trailing_surrogate(cmd.charAt(end))) - end++; - - if (start >= 0 && start < cmd.length) { - if (last_fun === kill_region) { - kill_region(start, end, dir); - } else { - cmd = cmd.substring(0, start) + cmd.substring(end); - cursor_pos = start; - } - } - } - - function delete_char() { - delete_char_dir(1); - } - - function control_d() { - if (cmd.length == 0) { - std.puts("\n"); - return -3; /* exit read eval print loop */ - } else { - delete_char_dir(1); - } - } - - function backward_delete_char() { - delete_char_dir(-1); - } - - function transpose_chars() { - var pos = cursor_pos; - if (cmd.length > 1 && pos > 0) { - if (pos == cmd.length) - pos--; - cmd = cmd.substring(0, pos - 1) + cmd.substring(pos, pos + 1) + - cmd.substring(pos - 1, pos) + cmd.substring(pos + 1); - cursor_pos = pos + 1; - } - } - - function transpose_words() { - var p1 = skip_word_backward(cursor_pos); - var p2 = skip_word_forward(p1); - var p4 = skip_word_forward(cursor_pos); - var p3 = skip_word_backward(p4); - - if (p1 < p2 && p2 <= cursor_pos && cursor_pos <= p3 && p3 < p4) { - cmd = cmd.substring(0, p1) + cmd.substring(p3, p4) + - cmd.substring(p2, p3) + cmd.substring(p1, p2); - cursor_pos = p4; - } - } - - function upcase_word() { - var end = skip_word_forward(cursor_pos); - cmd = cmd.substring(0, cursor_pos) + - cmd.substring(cursor_pos, end).toUpperCase() + - cmd.substring(end); - } - - function downcase_word() { - var end = skip_word_forward(cursor_pos); - cmd = cmd.substring(0, cursor_pos) + - cmd.substring(cursor_pos, end).toLowerCase() + - cmd.substring(end); - } - - function kill_region(start, end, dir) { - var s = cmd.substring(start, end); - if (last_fun !== kill_region) - clip_board = s; - else if (dir < 0) - clip_board = s + clip_board; - else - clip_board = clip_board + s; - - cmd = cmd.substring(0, start) + cmd.substring(end); - if (cursor_pos > end) - cursor_pos -= end - start; - else if (cursor_pos > start) - cursor_pos = start; - this_fun = kill_region; - } - - function kill_line() { - kill_region(cursor_pos, cmd.length, 1); - } - - function backward_kill_line() { - kill_region(0, cursor_pos, -1); - } - - function kill_word() { - kill_region(cursor_pos, skip_word_forward(cursor_pos), 1); - } - - function backward_kill_word() { - kill_region(skip_word_backward(cursor_pos), cursor_pos, -1); - } - - function yank() { - insert(clip_board); - } - - function control_c() { - if (last_fun === control_c) { - std.puts("\n"); - std.exit(0); - } else { - std.puts("\n(Press Ctrl-C again to quit)\n"); - readline_print_prompt(); - } - } - - function reset() { - cmd = ""; - cursor_pos = 0; - } - - function get_context_word(line, pos) { - var s = ""; - while (pos > 0 && is_word(line[pos - 1])) { - pos--; - s = line[pos] + s; - } - return s; - } - function get_context_object(line, pos) { - var obj, base, c; - if (pos <= 0 || " ~!%^&*(-+={[|:;,<>?/".indexOf(line[pos - 1]) >= 0) - return g; - if (pos >= 2 && line[pos - 1] === ".") { - pos--; - obj = {}; - switch (c = line[pos - 1]) { - case '\'': - case '\"': - return "a"; - case ']': - return []; - case '}': - return {}; - case '/': - return / /; - default: - if (is_word(c)) { - base = get_context_word(line, pos); - if (["true", "false", "null", "this"].includes(base) || !isNaN(+base)) - return eval(base); - obj = get_context_object(line, pos - base.length); - if (obj === null || obj === void 0) - return obj; - if (obj === g && obj[base] === void 0) - return eval(base); - else - return obj[base]; - } - return {}; - } - } - return void 0; - } - - function get_completions(line, pos) { - var s, obj, ctx_obj, r, i, j, paren; - - s = get_context_word(line, pos); - ctx_obj = get_context_object(line, pos - s.length); - r = []; - /* enumerate properties from object and its prototype chain, - add non-numeric regular properties with s as e prefix - */ - for (i = 0, obj = ctx_obj; i < 10 && obj !== null && obj !== void 0; i++) { - var props = Object.getOwnPropertyNames(obj); - /* add non-numeric regular properties */ - for (j = 0; j < props.length; j++) { - var prop = props[j]; - if (typeof prop == "string" && ""+(+prop) != prop && prop.startsWith(s)) - r.push(prop); - } - obj = Object.getPrototypeOf(obj); - } - if (r.length > 1) { - /* sort list with internal names last and remove duplicates */ - function symcmp(a, b) { - if (a[0] != b[0]) { - if (a[0] == '_') - return 1; - if (b[0] == '_') - return -1; - } - if (a < b) - return -1; - if (a > b) - return +1; - return 0; - } - r.sort(symcmp); - for(i = j = 1; i < r.length; i++) { - if (r[i] != r[i - 1]) - r[j++] = r[i]; - } - r.length = j; - } - /* 'tab' = list of completions, 'pos' = cursor position inside - the completions */ - return { tab: r, pos: s.length, ctx: ctx_obj }; - } - - function completion() { - var tab, res, s, i, j, len, t, max_width, col, n_cols, row, n_rows; - res = get_completions(cmd, cursor_pos); - tab = res.tab; - if (tab.length === 0) - return; - s = tab[0]; - len = s.length; - /* add the chars which are identical in all the completions */ - for(i = 1; i < tab.length; i++) { - t = tab[i]; - for(j = 0; j < len; j++) { - if (t[j] !== s[j]) { - len = j; - break; - } - } - } - for(i = res.pos; i < len; i++) { - insert(s[i]); - } - if (last_fun === completion && tab.length == 1) { - /* append parentheses to function names */ - var m = res.ctx[tab[0]]; - if (typeof m == "function") { - insert('('); - if (m.length == 0) - insert(')'); - } else if (typeof m == "object") { - insert('.'); - } - } - /* show the possible completions */ - if (last_fun === completion && tab.length >= 2) { - max_width = 0; - for(i = 0; i < tab.length; i++) - max_width = Math.max(max_width, tab[i].length); - max_width += 2; - n_cols = Math.max(1, Math.floor((term_width + 1) / max_width)); - n_rows = Math.ceil(tab.length / n_cols); - std.puts("\n"); - /* display the sorted list column-wise */ - for (row = 0; row < n_rows; row++) { - for (col = 0; col < n_cols; col++) { - i = col * n_rows + row; - if (i >= tab.length) - break; - s = tab[i]; - if (col != n_cols - 1) - s = s.padEnd(max_width); - std.puts(s); - } - std.puts("\n"); - } - /* show a new prompt */ - readline_print_prompt(); - } - } - - var commands = { /* command table */ - "\x01": beginning_of_line, /* ^A - bol */ - "\x02": backward_char, /* ^B - backward-char */ - "\x03": control_c, /* ^C - abort */ - "\x04": control_d, /* ^D - delete-char or exit */ - "\x05": end_of_line, /* ^E - eol */ - "\x06": forward_char, /* ^F - forward-char */ - "\x07": abort, /* ^G - bell */ - "\x08": backward_delete_char, /* ^H - backspace */ - "\x09": completion, /* ^I - history-search-backward */ - "\x0a": accept_line, /* ^J - newline */ - "\x0b": kill_line, /* ^K - delete to end of line */ - "\x0d": accept_line, /* ^M - enter */ - "\x0e": next_history, /* ^N - down */ - "\x10": previous_history, /* ^P - up */ - "\x11": quoted_insert, /* ^Q - quoted-insert */ - "\x12": alert, /* ^R - reverse-search */ - "\x13": alert, /* ^S - search */ - "\x14": transpose_chars, /* ^T - transpose */ - "\x18": reset, /* ^X - cancel */ - "\x19": yank, /* ^Y - yank */ - "\x1bOA": previous_history, /* ^[OA - up */ - "\x1bOB": next_history, /* ^[OB - down */ - "\x1bOC": forward_char, /* ^[OC - right */ - "\x1bOD": backward_char, /* ^[OD - left */ - "\x1bOF": forward_word, /* ^[OF - ctrl-right */ - "\x1bOH": backward_word, /* ^[OH - ctrl-left */ - "\x1b[1;5C": forward_word, /* ^[[1;5C - ctrl-right */ - "\x1b[1;5D": backward_word, /* ^[[1;5D - ctrl-left */ - "\x1b[1~": beginning_of_line, /* ^[[1~ - bol */ - "\x1b[3~": delete_char, /* ^[[3~ - delete */ - "\x1b[4~": end_of_line, /* ^[[4~ - eol */ - "\x1b[5~": history_search_backward,/* ^[[5~ - page up */ - "\x1b[6~": history_search_forward, /* ^[[5~ - page down */ - "\x1b[A": previous_history, /* ^[[A - up */ - "\x1b[B": next_history, /* ^[[B - down */ - "\x1b[C": forward_char, /* ^[[C - right */ - "\x1b[D": backward_char, /* ^[[D - left */ - "\x1b[F": end_of_line, /* ^[[F - end */ - "\x1b[H": beginning_of_line, /* ^[[H - home */ - "\x1b\x7f": backward_kill_word, /* M-C-? - backward_kill_word */ - "\x1bb": backward_word, /* M-b - backward_word */ - "\x1bd": kill_word, /* M-d - kill_word */ - "\x1bf": forward_word, /* M-f - backward_word */ - "\x1bk": backward_kill_line, /* M-k - backward_kill_line */ - "\x1bl": downcase_word, /* M-l - downcase_word */ - "\x1bt": transpose_words, /* M-t - transpose_words */ - "\x1bu": upcase_word, /* M-u - upcase_word */ - "\x7f": backward_delete_char, /* ^? - delete */ - }; - - function dupstr(str, count) { - var res = ""; - while (count-- > 0) - res += str; - return res; - } - - var readline_keys; - var readline_state; - var readline_cb; - - function readline_print_prompt() - { - std.puts(prompt); - term_cursor_x = ucs_length(prompt) % term_width; - last_cmd = ""; - last_cursor_pos = 0; - } - - function readline_start(defstr, cb) { - cmd = defstr || ""; - cursor_pos = cmd.length; - history_index = history.length; - readline_cb = cb; - - prompt = pstate; - - if (mexpr) { - prompt += dupstr(" ", plen - prompt.length); - prompt += ps2; - } else { - if (show_time) { - var t = Math.round(eval_time) + " "; - eval_time = 0; - t = dupstr("0", 5 - t.length) + t; - prompt += t.substring(0, t.length - 4) + "." + t.substring(t.length - 4); - } - plen = prompt.length; - prompt += ps1; - } - readline_print_prompt(); - update(); - readline_state = 0; - } - - function handle_char(c1) { - var c; - c = String.fromCodePoint(c1); - switch(readline_state) { - case 0: - if (c == '\x1b') { /* '^[' - ESC */ - readline_keys = c; - readline_state = 1; - } else { - handle_key(c); - } - break; - case 1: /* '^[ */ - readline_keys += c; - if (c == '[') { - readline_state = 2; - } else if (c == 'O') { - readline_state = 3; - } else { - handle_key(readline_keys); - readline_state = 0; - } - break; - case 2: /* '^[[' - CSI */ - readline_keys += c; - if (!(c == ';' || (c >= '0' && c <= '9'))) { - handle_key(readline_keys); - readline_state = 0; - } - break; - case 3: /* '^[O' - ESC2 */ - readline_keys += c; - handle_key(readline_keys); - readline_state = 0; - break; - } - } - - function handle_key(keys) { - var fun; - - if (quote_flag) { - if (ucs_length(keys) === 1) - insert(keys); - quote_flag = false; - } else if (fun = commands[keys]) { - this_fun = fun; - switch (fun(keys)) { - case -1: - readline_cb(cmd); - return; - case -2: - readline_cb(null); - return; - case -3: - /* uninstall a Ctrl-C signal handler */ - os.signal(os.SIGINT, null); - /* uninstall the stdin read handler */ - os.setReadHandler(term_fd, null); - return; - } - last_fun = this_fun; - } else if (ucs_length(keys) === 1 && keys >= ' ') { - insert(keys); - last_fun = insert; - } else { - alert(); /* beep! */ - } - - cursor_pos = (cursor_pos < 0) ? 0 : - (cursor_pos > cmd.length) ? cmd.length : cursor_pos; - update(); - } - - var hex_mode = false; - var eval_mode = "std"; - - function number_to_string(a, radix) { - var s; - if (!isFinite(a)) { - /* NaN, Infinite */ - return a.toString(); - } else { - if (a == 0) { - if (1 / a < 0) - s = "-0"; - else - s = "0"; - } else { - if (radix == 16 && a === Math.floor(a)) { - var s; - if (a < 0) { - a = -a; - s = "-"; - } else { - s = ""; - } - s += "0x" + a.toString(16); - } else { - s = a.toString(); - } - } - return s; - } - } - - function bigfloat_to_string(a, radix) { - var s; - if (!BigFloat.isFinite(a)) { - /* NaN, Infinite */ - if (eval_mode !== "math") { - return "BigFloat(" + a.toString() + ")"; - } else { - return a.toString(); - } - } else { - if (a == 0) { - if (1 / a < 0) - s = "-0"; - else - s = "0"; - } else { - if (radix == 16) { - var s; - if (a < 0) { - a = -a; - s = "-"; - } else { - s = ""; - } - s += "0x" + a.toString(16); - } else { - s = a.toString(); - } - } - if (typeof a === "bigfloat" && eval_mode !== "math") { - s += "l"; - } else if (eval_mode !== "std" && s.indexOf(".") < 0 && - ((radix == 16 && s.indexOf("p") < 0) || - (radix == 10 && s.indexOf("e") < 0))) { - /* add a decimal point so that the floating point type - is visible */ - s += ".0"; - } - return s; - } - } - - function bigint_to_string(a, radix) { - var s; - if (radix == 16) { - var s; - if (a < 0) { - a = -a; - s = "-"; - } else { - s = ""; - } - s += "0x" + a.toString(16); - } else { - s = a.toString(); - } - if (eval_mode === "std") - s += "n"; - return s; - } - - function print(a) { - var stack = []; - - function print_rec(a) { - var n, i, keys, key, type, s; - - type = typeof(a); - if (type === "object") { - if (a === null) { - std.puts(a); - } else if (stack.indexOf(a) >= 0) { - std.puts("[circular]"); - } else if (has_jscalc && (a instanceof Fraction || - a instanceof Complex || - a instanceof Mod || - a instanceof Polynomial || - a instanceof PolyMod || - a instanceof RationalFunction || - a instanceof Series)) { - std.puts(a.toString()); - } else { - stack.push(a); - if (Array.isArray(a)) { - n = a.length; - std.puts("[ "); - for(i = 0; i < n; i++) { - if (i !== 0) - std.puts(", "); - if (i in a) { - print_rec(a[i]); - } else { - std.puts(""); - } - if (i > 20) { - std.puts("..."); - break; - } - } - std.puts(" ]"); - } else if (Object.__getClass(a) === "RegExp") { - std.puts(a.toString()); - } else { - keys = Object.keys(a); - n = keys.length; - std.puts("{ "); - for(i = 0; i < n; i++) { - if (i !== 0) - std.puts(", "); - key = keys[i]; - std.puts(key, ": "); - print_rec(a[key]); - } - std.puts(" }"); - } - stack.pop(a); - } - } else if (type === "string") { - s = a.__quote(); - if (s.length > 79) - s = s.substring(0, 75) + "...\""; - std.puts(s); - } else if (type === "number") { - std.puts(number_to_string(a, hex_mode ? 16 : 10)); - } else if (type === "bigint") { - std.puts(bigint_to_string(a, hex_mode ? 16 : 10)); - } else if (type === "bigfloat") { - std.puts(bigfloat_to_string(a, hex_mode ? 16 : 10)); - } else if (type === "bigdecimal") { - std.puts(a.toString() + "m"); - } else if (type === "symbol") { - std.puts(String(a)); - } else if (type === "function") { - std.puts("function " + a.name + "()"); - } else { - std.puts(a); - } - } - print_rec(a); - } - - function extract_directive(a) { - var pos; - if (a[0] !== '\\') - return ""; - for (pos = 1; pos < a.length; pos++) { - if (!is_alpha(a[pos])) - break; - } - return a.substring(1, pos); - } - - /* return true if the string after cmd can be evaluted as JS */ - function handle_directive(cmd, expr) { - var param, prec1, expBits1; - - if (cmd === "h" || cmd === "?" || cmd == "help") { - help(); - } else if (cmd === "load") { - var filename = expr.substring(cmd.length + 1).trim(); - if (filename.lastIndexOf(".") <= filename.lastIndexOf("/")) - filename += ".js"; - std.loadScript(filename); - return false; - } else if (cmd === "x") { - hex_mode = true; - } else if (cmd === "d") { - hex_mode = false; - } else if (cmd === "t") { - show_time = !show_time; - } else if (has_bignum && cmd === "p") { - param = expr.substring(cmd.length + 1).trim().split(" "); - if (param.length === 1 && param[0] === "") { - std.puts("BigFloat precision=" + prec + " bits (~" + - Math.floor(prec / log2_10) + - " digits), exponent size=" + expBits + " bits\n"); - } else if (param[0] === "f16") { - prec = 11; - expBits = 5; - } else if (param[0] === "f32") { - prec = 24; - expBits = 8; - } else if (param[0] === "f64") { - prec = 53; - expBits = 11; - } else if (param[0] === "f128") { - prec = 113; - expBits = 15; - } else { - prec1 = parseInt(param[0]); - if (param.length >= 2) - expBits1 = parseInt(param[1]); - else - expBits1 = BigFloatEnv.expBitsMax; - if (Number.isNaN(prec1) || - prec1 < BigFloatEnv.precMin || - prec1 > BigFloatEnv.precMax) { - std.puts("Invalid precision\n"); - return false; - } - if (Number.isNaN(expBits1) || - expBits1 < BigFloatEnv.expBitsMin || - expBits1 > BigFloatEnv.expBitsMax) { - std.puts("Invalid exponent bits\n"); - return false; - } - prec = prec1; - expBits = expBits1; - } - return false; - } else if (has_bignum && cmd === "digits") { - param = expr.substring(cmd.length + 1).trim(); - prec1 = Math.ceil(parseFloat(param) * log2_10); - if (prec1 < BigFloatEnv.precMin || - prec1 > BigFloatEnv.precMax) { - std.puts("Invalid precision\n"); - return false; - } - prec = prec1; - expBits = BigFloatEnv.expBitsMax; - return false; - } else if (has_bignum && cmd === "mode") { - param = expr.substring(cmd.length + 1).trim(); - if (param === "") { - std.puts("Running mode=" + eval_mode + "\n"); - } else if (param === "std" || param === "math") { - eval_mode = param; - } else { - std.puts("Invalid mode\n"); - } - return false; - } else if (cmd === "clear") { - std.puts("\x1b[H\x1b[J"); - } else if (cmd === "q") { - std.exit(0); - } else if (has_jscalc && cmd === "a") { - algebraicMode = true; - } else if (has_jscalc && cmd === "n") { - algebraicMode = false; - } else { - std.puts("Unknown directive: " + cmd + "\n"); - return false; - } - return true; - } - - if (config_numcalc) { - /* called by the GUI */ - g.execCmd = function (cmd) { - switch(cmd) { - case "dec": - hex_mode = false; - break; - case "hex": - hex_mode = true; - break; - case "num": - algebraicMode = false; - break; - case "alg": - algebraicMode = true; - break; - } - } - } - - function help() { - function sel(n) { - return n ? "*": " "; - } - std.puts("\\h this help\n" + - "\\x " + sel(hex_mode) + "hexadecimal number display\n" + - "\\d " + sel(!hex_mode) + "decimal number display\n" + - "\\t " + sel(show_time) + "toggle timing display\n" + - "\\clear clear the terminal\n"); - if (has_jscalc) { - std.puts("\\a " + sel(algebraicMode) + "algebraic mode\n" + - "\\n " + sel(!algebraicMode) + "numeric mode\n"); - } - if (has_bignum) { - std.puts("\\p [m [e]] set the BigFloat precision to 'm' bits\n" + - "\\digits n set the BigFloat precision to 'ceil(n*log2(10))' bits\n"); - if (!has_jscalc) { - std.puts("\\mode [std|math] change the running mode (current = " + eval_mode + ")\n"); - } - } - if (!config_numcalc) { - std.puts("\\q exit\n"); - } - } - - function eval_and_print(expr) { - var result; - - try { - if (eval_mode === "math") - expr = '"use math"; void 0;' + expr; - var now = (new Date).getTime(); - /* eval as a script */ - result = std.evalScript(expr, { backtrace_barrier: true }); - eval_time = (new Date).getTime() - now; - std.puts(colors[styles.result]); - print(result); - std.puts("\n"); - std.puts(colors.none); - /* set the last result */ - g._ = result; - } catch (error) { - std.puts(colors[styles.error_msg]); - if (error instanceof Error) { - console.log(error); - if (error.stack) { - std.puts(error.stack); - } - } else { - std.puts("Throw: "); - console.log(error); - } - std.puts(colors.none); - } - } - - function cmd_start() { - if (!config_numcalc) { - if (has_jscalc) - std.puts('QJSCalc - Type "\\h" for help\n'); - else - std.puts('QuickJS - Type "\\h" for help\n'); - } - if (has_bignum) { - log2_10 = Math.log(10) / Math.log(2); - prec = 113; - expBits = 15; - if (has_jscalc) { - eval_mode = "math"; - /* XXX: numeric mode should always be the default ? */ - g.algebraicMode = config_numcalc; - } - } - - cmd_readline_start(); - } - - function cmd_readline_start() { - readline_start(dupstr(" ", level), readline_handle_cmd); - } - - function readline_handle_cmd(expr) { - handle_cmd(expr); - cmd_readline_start(); - } - - function handle_cmd(expr) { - var colorstate, cmd; - - if (expr === null) { - expr = ""; - return; - } - if (expr === "?") { - help(); - return; - } - cmd = extract_directive(expr); - if (cmd.length > 0) { - if (!handle_directive(cmd, expr)) - return; - expr = expr.substring(cmd.length + 1); - } - if (expr === "") - return; - - if (mexpr) - expr = mexpr + '\n' + expr; - colorstate = colorize_js(expr); - pstate = colorstate[0]; - level = colorstate[1]; - if (pstate) { - mexpr = expr; - return; - } - mexpr = ""; - - if (has_bignum) { - BigFloatEnv.setPrec(eval_and_print.bind(null, expr), - prec, expBits); - } else { - eval_and_print(expr); - } - level = 0; - - /* run the garbage collector after each command */ - std.gc(); - } - - function colorize_js(str) { - var i, c, start, n = str.length; - var style, state = "", level = 0; - var primary, can_regex = 1; - var r = []; - - function push_state(c) { state += c; } - function last_state(c) { return state.substring(state.length - 1); } - function pop_state(c) { - var c = last_state(); - state = state.substring(0, state.length - 1); - return c; - } - - function parse_block_comment() { - style = 'comment'; - push_state('/'); - for (i++; i < n - 1; i++) { - if (str[i] == '*' && str[i + 1] == '/') { - i += 2; - pop_state('/'); - break; - } - } - } - - function parse_line_comment() { - style = 'comment'; - for (i++; i < n; i++) { - if (str[i] == '\n') { - break; - } - } - } - - function parse_string(delim) { - style = 'string'; - push_state(delim); - while (i < n) { - c = str[i++]; - if (c == '\n') { - style = 'error'; - continue; - } - if (c == '\\') { - if (i >= n) - break; - i++; - } else - if (c == delim) { - pop_state(); - break; - } - } - } - - function parse_regex() { - style = 'regex'; - push_state('/'); - while (i < n) { - c = str[i++]; - if (c == '\n') { - style = 'error'; - continue; - } - if (c == '\\') { - if (i < n) { - i++; - } - continue; - } - if (last_state() == '[') { - if (c == ']') { - pop_state() - } - // ECMA 5: ignore '/' inside char classes - continue; - } - if (c == '[') { - push_state('['); - if (str[i] == '[' || str[i] == ']') - i++; - continue; - } - if (c == '/') { - pop_state(); - while (i < n && is_word(str[i])) - i++; - break; - } - } - } - - function parse_number() { - style = 'number'; - while (i < n && (is_word(str[i]) || (str[i] == '.' && (i == n - 1 || str[i + 1] != '.')))) { - i++; - } - } - - var js_keywords = "|" + - "break|case|catch|continue|debugger|default|delete|do|" + - "else|finally|for|function|if|in|instanceof|new|" + - "return|switch|this|throw|try|typeof|while|with|" + - "class|const|enum|import|export|extends|super|" + - "implements|interface|let|package|private|protected|" + - "public|static|yield|" + - "undefined|null|true|false|Infinity|NaN|" + - "eval|arguments|" + - "await|"; - - var js_no_regex = "|this|super|undefined|null|true|false|Infinity|NaN|arguments|"; - var js_types = "|void|var|"; - - function parse_identifier() { - can_regex = 1; - - while (i < n && is_word(str[i])) - i++; - - var w = '|' + str.substring(start, i) + '|'; - - if (js_keywords.indexOf(w) >= 0) { - style = 'keyword'; - if (js_no_regex.indexOf(w) >= 0) - can_regex = 0; - return; - } - - var i1 = i; - while (i1 < n && str[i1] == ' ') - i1++; - - if (i1 < n && str[i1] == '(') { - style = 'function'; - return; - } - - if (js_types.indexOf(w) >= 0) { - style = 'type'; - return; - } - - style = 'identifier'; - can_regex = 0; - } - - function set_style(from, to) { - while (r.length < from) - r.push('default'); - while (r.length < to) - r.push(style); - } - - for (i = 0; i < n;) { - style = null; - start = i; - switch (c = str[i++]) { - case ' ': - case '\t': - case '\r': - case '\n': - continue; - case '+': - case '-': - if (i < n && str[i] == c) { - i++; - continue; - } - can_regex = 1; - continue; - case '/': - if (i < n && str[i] == '*') { // block comment - parse_block_comment(); - break; - } - if (i < n && str[i] == '/') { // line comment - parse_line_comment(); - break; - } - if (can_regex) { - parse_regex(); - can_regex = 0; - break; - } - can_regex = 1; - continue; - case '\'': - case '\"': - case '`': - parse_string(c); - can_regex = 0; - break; - case '(': - case '[': - case '{': - can_regex = 1; - level++; - push_state(c); - continue; - case ')': - case ']': - case '}': - can_regex = 0; - if (level > 0 && is_balanced(last_state(), c)) { - level--; - pop_state(); - continue; - } - style = 'error'; - break; - default: - if (is_digit(c)) { - parse_number(); - can_regex = 0; - break; - } - if (is_word(c) || c == '$') { - parse_identifier(); - break; - } - can_regex = 1; - continue; - } - if (style) - set_style(start, i); - } - set_style(n, n); - return [ state, level, r ]; - } - - termInit(); - - cmd_start(); - -})(globalThis); diff --git a/quickjs/run-test262.c b/quickjs/run-test262.c deleted file mode 100644 index 2092cac..0000000 --- a/quickjs/run-test262.c +++ /dev/null @@ -1,2107 +0,0 @@ -/* - * ECMA Test 262 Runner for QuickJS - * - * Copyright (c) 2017-2021 Fabrice Bellard - * Copyright (c) 2017-2021 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "cutils.h" -#include "list.h" -#include "quickjs-libc.h" - -/* enable test262 thread support to test SharedArrayBuffer and Atomics */ -#define CONFIG_AGENT - -#define CMD_NAME "run-test262" - -typedef struct namelist_t { - char **array; - int count; - int size; - unsigned int sorted : 1; -} namelist_t; - -namelist_t test_list; -namelist_t exclude_list; -namelist_t exclude_dir_list; - -FILE *outfile; -enum test_mode_t { - TEST_DEFAULT_NOSTRICT, /* run tests as nostrict unless test is flagged as strictonly */ - TEST_DEFAULT_STRICT, /* run tests as strict unless test is flagged as nostrict */ - TEST_NOSTRICT, /* run tests as nostrict, skip strictonly tests */ - TEST_STRICT, /* run tests as strict, skip nostrict tests */ - TEST_ALL, /* run tests in both strict and nostrict, unless restricted by spec */ -} test_mode = TEST_DEFAULT_NOSTRICT; -int skip_async; -int skip_module; -int new_style; -int dump_memory; -int stats_count; -JSMemoryUsage stats_all, stats_avg, stats_min, stats_max; -char *stats_min_filename; -char *stats_max_filename; -int verbose; -char *harness_dir; -char *harness_exclude; -char *harness_features; -char *harness_skip_features; -char *error_filename; -char *error_file; -FILE *error_out; -char *report_filename; -int update_errors; -int test_count, test_failed, test_index, test_skipped, test_excluded; -int new_errors, changed_errors, fixed_errors; -int async_done; - -void warning(const char *, ...) __attribute__((__format__(__printf__, 1, 2))); -void fatal(int, const char *, ...) __attribute__((__format__(__printf__, 2, 3))); - -void warning(const char *fmt, ...) -{ - va_list ap; - - fflush(stdout); - fprintf(stderr, "%s: ", CMD_NAME); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputc('\n', stderr); -} - -void fatal(int errcode, const char *fmt, ...) -{ - va_list ap; - - fflush(stdout); - fprintf(stderr, "%s: ", CMD_NAME); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputc('\n', stderr); - - exit(errcode); -} - -void perror_exit(int errcode, const char *s) -{ - fflush(stdout); - fprintf(stderr, "%s: ", CMD_NAME); - perror(s); - exit(errcode); -} - -char *strdup_len(const char *str, int len) -{ - char *p = malloc(len + 1); - memcpy(p, str, len); - p[len] = '\0'; - return p; -} - -static inline int str_equal(const char *a, const char *b) { - return !strcmp(a, b); -} - -char *str_append(char **pp, const char *sep, const char *str) { - char *res, *p; - size_t len = 0; - p = *pp; - if (p) { - len = strlen(p) + strlen(sep); - } - res = malloc(len + strlen(str) + 1); - if (p) { - strcpy(res, p); - strcat(res, sep); - } - strcpy(res + len, str); - free(p); - return *pp = res; -} - -char *str_strip(char *p) -{ - size_t len = strlen(p); - while (len > 0 && isspace((unsigned char)p[len - 1])) - p[--len] = '\0'; - while (isspace((unsigned char)*p)) - p++; - return p; -} - -int has_prefix(const char *str, const char *prefix) -{ - return !strncmp(str, prefix, strlen(prefix)); -} - -char *skip_prefix(const char *str, const char *prefix) -{ - int i; - for (i = 0;; i++) { - if (prefix[i] == '\0') { /* skip the prefix */ - str += i; - break; - } - if (str[i] != prefix[i]) - break; - } - return (char *)str; -} - -char *get_basename(const char *filename) -{ - char *p; - - p = strrchr(filename, '/'); - if (!p) - return NULL; - return strdup_len(filename, p - filename); -} - -char *compose_path(const char *path, const char *name) -{ - int path_len, name_len; - char *d, *q; - - if (!path || path[0] == '\0' || *name == '/') { - d = strdup(name); - } else { - path_len = strlen(path); - name_len = strlen(name); - d = malloc(path_len + 1 + name_len + 1); - if (d) { - q = d; - memcpy(q, path, path_len); - q += path_len; - if (path[path_len - 1] != '/') - *q++ = '/'; - memcpy(q, name, name_len + 1); - } - } - return d; -} - -int namelist_cmp(const char *a, const char *b) -{ - /* compare strings in modified lexicographical order */ - for (;;) { - int ca = (unsigned char)*a++; - int cb = (unsigned char)*b++; - if (isdigit(ca) && isdigit(cb)) { - int na = ca - '0'; - int nb = cb - '0'; - while (isdigit(ca = (unsigned char)*a++)) - na = na * 10 + ca - '0'; - while (isdigit(cb = (unsigned char)*b++)) - nb = nb * 10 + cb - '0'; - if (na < nb) - return -1; - if (na > nb) - return +1; - } - if (ca < cb) - return -1; - if (ca > cb) - return +1; - if (ca == '\0') - return 0; - } -} - -int namelist_cmp_indirect(const void *a, const void *b) -{ - return namelist_cmp(*(const char **)a, *(const char **)b); -} - -void namelist_sort(namelist_t *lp) -{ - int i, count; - if (lp->count > 1) { - qsort(lp->array, lp->count, sizeof(*lp->array), namelist_cmp_indirect); - /* remove duplicates */ - for (count = i = 1; i < lp->count; i++) { - if (namelist_cmp(lp->array[count - 1], lp->array[i]) == 0) { - free(lp->array[i]); - } else { - lp->array[count++] = lp->array[i]; - } - } - lp->count = count; - } - lp->sorted = 1; -} - -int namelist_find(namelist_t *lp, const char *name) -{ - int a, b, m, cmp; - - if (!lp->sorted) { - namelist_sort(lp); - } - for (a = 0, b = lp->count; a < b;) { - m = a + (b - a) / 2; - cmp = namelist_cmp(lp->array[m], name); - if (cmp < 0) - a = m + 1; - else if (cmp > 0) - b = m; - else - return m; - } - return -1; -} - -void namelist_add(namelist_t *lp, const char *base, const char *name) -{ - char *s; - - s = compose_path(base, name); - if (!s) - goto fail; - if (lp->count == lp->size) { - size_t newsize = lp->size + (lp->size >> 1) + 4; - char **a = realloc(lp->array, sizeof(lp->array[0]) * newsize); - if (!a) - goto fail; - lp->array = a; - lp->size = newsize; - } - lp->array[lp->count] = s; - lp->count++; - return; -fail: - fatal(1, "allocation failure\n"); -} - -void namelist_load(namelist_t *lp, const char *filename) -{ - char buf[1024]; - char *base_name; - FILE *f; - - f = fopen(filename, "rb"); - if (!f) { - perror_exit(1, filename); - } - base_name = get_basename(filename); - - while (fgets(buf, sizeof(buf), f) != NULL) { - char *p = str_strip(buf); - if (*p == '#' || *p == ';' || *p == '\0') - continue; /* line comment */ - - namelist_add(lp, base_name, p); - } - free(base_name); - fclose(f); -} - -void namelist_add_from_error_file(namelist_t *lp, const char *file) -{ - const char *p, *p0; - char *pp; - - for (p = file; (p = strstr(p, ".js:")) != NULL; p++) { - for (p0 = p; p0 > file && p0[-1] != '\n'; p0--) - continue; - pp = strdup_len(p0, p + 3 - p0); - namelist_add(lp, NULL, pp); - free(pp); - } -} - -void namelist_free(namelist_t *lp) -{ - while (lp->count > 0) { - free(lp->array[--lp->count]); - } - free(lp->array); - lp->array = NULL; - lp->size = 0; -} - -static int add_test_file(const char *filename, const struct stat *ptr, int flag) -{ - namelist_t *lp = &test_list; - if (has_suffix(filename, ".js") && !has_suffix(filename, "_FIXTURE.js")) - namelist_add(lp, NULL, filename); - return 0; -} - -/* find js files from the directory tree and sort the list */ -static void enumerate_tests(const char *path) -{ - namelist_t *lp = &test_list; - int start = lp->count; - ftw(path, add_test_file, 100); - qsort(lp->array + start, lp->count - start, sizeof(*lp->array), - namelist_cmp_indirect); -} - -static JSValue js_print(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - int i; - const char *str; - - if (outfile) { - for (i = 0; i < argc; i++) { - if (i != 0) - fputc(' ', outfile); - str = JS_ToCString(ctx, argv[i]); - if (!str) - return JS_EXCEPTION; - if (!strcmp(str, "Test262:AsyncTestComplete")) { - async_done++; - } else if (strstart(str, "Test262:AsyncTestFailure", NULL)) { - async_done = 2; /* force an error */ - } - fputs(str, outfile); - JS_FreeCString(ctx, str); - } - fputc('\n', outfile); - } - return JS_UNDEFINED; -} - -static JSValue js_detachArrayBuffer(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - JS_DetachArrayBuffer(ctx, argv[0]); - return JS_UNDEFINED; -} - -static JSValue js_evalScript(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - const char *str; - size_t len; - JSValue ret; - str = JS_ToCStringLen(ctx, &len, argv[0]); - if (!str) - return JS_EXCEPTION; - ret = JS_Eval(ctx, str, len, "", JS_EVAL_TYPE_GLOBAL); - JS_FreeCString(ctx, str); - return ret; -} - -#ifdef CONFIG_AGENT - -#include - -typedef struct { - struct list_head link; - pthread_t tid; - char *script; - JSValue broadcast_func; - BOOL broadcast_pending; - JSValue broadcast_sab; /* in the main context */ - uint8_t *broadcast_sab_buf; - size_t broadcast_sab_size; - int32_t broadcast_val; -} Test262Agent; - -typedef struct { - struct list_head link; - char *str; -} AgentReport; - -static JSValue add_helpers1(JSContext *ctx); -static void add_helpers(JSContext *ctx); - -static pthread_mutex_t agent_mutex = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t agent_cond = PTHREAD_COND_INITIALIZER; -/* list of Test262Agent.link */ -static struct list_head agent_list = LIST_HEAD_INIT(agent_list); - -static pthread_mutex_t report_mutex = PTHREAD_MUTEX_INITIALIZER; -/* list of AgentReport.link */ -static struct list_head report_list = LIST_HEAD_INIT(report_list); - -static void *agent_start(void *arg) -{ - Test262Agent *agent = arg; - JSRuntime *rt; - JSContext *ctx; - JSValue ret_val; - int ret; - - rt = JS_NewRuntime(); - if (rt == NULL) { - fatal(1, "JS_NewRuntime failure"); - } - ctx = JS_NewContext(rt); - if (ctx == NULL) { - JS_FreeRuntime(rt); - fatal(1, "JS_NewContext failure"); - } - JS_SetContextOpaque(ctx, agent); - JS_SetRuntimeInfo(rt, "agent"); - JS_SetCanBlock(rt, TRUE); - - add_helpers(ctx); - ret_val = JS_Eval(ctx, agent->script, strlen(agent->script), - "", JS_EVAL_TYPE_GLOBAL); - free(agent->script); - agent->script = NULL; - if (JS_IsException(ret_val)) - js_std_dump_error(ctx); - JS_FreeValue(ctx, ret_val); - - for(;;) { - JSContext *ctx1; - ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); - if (ret < 0) { - js_std_dump_error(ctx); - break; - } else if (ret == 0) { - if (JS_IsUndefined(agent->broadcast_func)) { - break; - } else { - JSValue args[2]; - - pthread_mutex_lock(&agent_mutex); - while (!agent->broadcast_pending) { - pthread_cond_wait(&agent_cond, &agent_mutex); - } - - agent->broadcast_pending = FALSE; - pthread_cond_signal(&agent_cond); - - pthread_mutex_unlock(&agent_mutex); - - args[0] = JS_NewArrayBuffer(ctx, agent->broadcast_sab_buf, - agent->broadcast_sab_size, - NULL, NULL, TRUE); - args[1] = JS_NewInt32(ctx, agent->broadcast_val); - ret_val = JS_Call(ctx, agent->broadcast_func, JS_UNDEFINED, - 2, (JSValueConst *)args); - JS_FreeValue(ctx, args[0]); - JS_FreeValue(ctx, args[1]); - if (JS_IsException(ret_val)) - js_std_dump_error(ctx); - JS_FreeValue(ctx, ret_val); - JS_FreeValue(ctx, agent->broadcast_func); - agent->broadcast_func = JS_UNDEFINED; - } - } - } - JS_FreeValue(ctx, agent->broadcast_func); - - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return NULL; -} - -static JSValue js_agent_start(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - const char *script; - Test262Agent *agent; - - if (JS_GetContextOpaque(ctx) != NULL) - return JS_ThrowTypeError(ctx, "cannot be called inside an agent"); - - script = JS_ToCString(ctx, argv[0]); - if (!script) - return JS_EXCEPTION; - agent = malloc(sizeof(*agent)); - memset(agent, 0, sizeof(*agent)); - agent->broadcast_func = JS_UNDEFINED; - agent->broadcast_sab = JS_UNDEFINED; - agent->script = strdup(script); - JS_FreeCString(ctx, script); - list_add_tail(&agent->link, &agent_list); - pthread_create(&agent->tid, NULL, agent_start, agent); - return JS_UNDEFINED; -} - -static void js_agent_free(JSContext *ctx) -{ - struct list_head *el, *el1; - Test262Agent *agent; - - list_for_each_safe(el, el1, &agent_list) { - agent = list_entry(el, Test262Agent, link); - pthread_join(agent->tid, NULL); - JS_FreeValue(ctx, agent->broadcast_sab); - list_del(&agent->link); - free(agent); - } -} - -static JSValue js_agent_leaving(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - Test262Agent *agent = JS_GetContextOpaque(ctx); - if (!agent) - return JS_ThrowTypeError(ctx, "must be called inside an agent"); - /* nothing to do */ - return JS_UNDEFINED; -} - -static BOOL is_broadcast_pending(void) -{ - struct list_head *el; - Test262Agent *agent; - list_for_each(el, &agent_list) { - agent = list_entry(el, Test262Agent, link); - if (agent->broadcast_pending) - return TRUE; - } - return FALSE; -} - -static JSValue js_agent_broadcast(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - JSValueConst sab = argv[0]; - struct list_head *el; - Test262Agent *agent; - uint8_t *buf; - size_t buf_size; - int32_t val; - - if (JS_GetContextOpaque(ctx) != NULL) - return JS_ThrowTypeError(ctx, "cannot be called inside an agent"); - - buf = JS_GetArrayBuffer(ctx, &buf_size, sab); - if (!buf) - return JS_EXCEPTION; - if (JS_ToInt32(ctx, &val, argv[1])) - return JS_EXCEPTION; - - /* broadcast the values and wait until all agents have started - calling their callbacks */ - pthread_mutex_lock(&agent_mutex); - list_for_each(el, &agent_list) { - agent = list_entry(el, Test262Agent, link); - agent->broadcast_pending = TRUE; - /* the shared array buffer is used by the thread, so increment - its refcount */ - agent->broadcast_sab = JS_DupValue(ctx, sab); - agent->broadcast_sab_buf = buf; - agent->broadcast_sab_size = buf_size; - agent->broadcast_val = val; - } - pthread_cond_broadcast(&agent_cond); - - while (is_broadcast_pending()) { - pthread_cond_wait(&agent_cond, &agent_mutex); - } - pthread_mutex_unlock(&agent_mutex); - return JS_UNDEFINED; -} - -static JSValue js_agent_receiveBroadcast(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - Test262Agent *agent = JS_GetContextOpaque(ctx); - if (!agent) - return JS_ThrowTypeError(ctx, "must be called inside an agent"); - if (!JS_IsFunction(ctx, argv[0])) - return JS_ThrowTypeError(ctx, "expecting function"); - JS_FreeValue(ctx, agent->broadcast_func); - agent->broadcast_func = JS_DupValue(ctx, argv[0]); - return JS_UNDEFINED; -} - -static JSValue js_agent_sleep(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - uint32_t duration; - if (JS_ToUint32(ctx, &duration, argv[0])) - return JS_EXCEPTION; - usleep(duration * 1000); - return JS_UNDEFINED; -} - -static int64_t get_clock_ms(void) -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return (uint64_t)ts.tv_sec * 1000 + (ts.tv_nsec / 1000000); -} - -static JSValue js_agent_monotonicNow(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - return JS_NewInt64(ctx, get_clock_ms()); -} - -static JSValue js_agent_getReport(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - AgentReport *rep; - JSValue ret; - - pthread_mutex_lock(&report_mutex); - if (list_empty(&report_list)) { - rep = NULL; - } else { - rep = list_entry(report_list.next, AgentReport, link); - list_del(&rep->link); - } - pthread_mutex_unlock(&report_mutex); - if (rep) { - ret = JS_NewString(ctx, rep->str); - free(rep->str); - free(rep); - } else { - ret = JS_NULL; - } - return ret; -} - -static JSValue js_agent_report(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - const char *str; - AgentReport *rep; - - str = JS_ToCString(ctx, argv[0]); - if (!str) - return JS_EXCEPTION; - rep = malloc(sizeof(*rep)); - rep->str = strdup(str); - JS_FreeCString(ctx, str); - - pthread_mutex_lock(&report_mutex); - list_add_tail(&rep->link, &report_list); - pthread_mutex_unlock(&report_mutex); - return JS_UNDEFINED; -} - -static const JSCFunctionListEntry js_agent_funcs[] = { - /* only in main */ - JS_CFUNC_DEF("start", 1, js_agent_start ), - JS_CFUNC_DEF("getReport", 0, js_agent_getReport ), - JS_CFUNC_DEF("broadcast", 2, js_agent_broadcast ), - /* only in agent */ - JS_CFUNC_DEF("report", 1, js_agent_report ), - JS_CFUNC_DEF("leaving", 0, js_agent_leaving ), - JS_CFUNC_DEF("receiveBroadcast", 1, js_agent_receiveBroadcast ), - /* in both */ - JS_CFUNC_DEF("sleep", 1, js_agent_sleep ), - JS_CFUNC_DEF("monotonicNow", 0, js_agent_monotonicNow ), -}; - -static JSValue js_new_agent(JSContext *ctx) -{ - JSValue agent; - agent = JS_NewObject(ctx); - JS_SetPropertyFunctionList(ctx, agent, js_agent_funcs, - countof(js_agent_funcs)); - return agent; -} -#endif - -static JSValue js_createRealm(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - JSContext *ctx1; - JSValue ret; - - ctx1 = JS_NewContext(JS_GetRuntime(ctx)); - if (!ctx1) - return JS_ThrowOutOfMemory(ctx); - ret = add_helpers1(ctx1); - /* ctx1 has a refcount so it stays alive */ - JS_FreeContext(ctx1); - return ret; -} - -static JSValue js_IsHTMLDDA(JSContext *ctx, JSValue this_val, - int argc, JSValue *argv) -{ - return JS_NULL; -} - -static JSValue add_helpers1(JSContext *ctx) -{ - JSValue global_obj; - JSValue obj262, obj; - - global_obj = JS_GetGlobalObject(ctx); - - JS_SetPropertyStr(ctx, global_obj, "print", - JS_NewCFunction(ctx, js_print, "print", 1)); - - /* $262 special object used by the tests */ - obj262 = JS_NewObject(ctx); - JS_SetPropertyStr(ctx, obj262, "detachArrayBuffer", - JS_NewCFunction(ctx, js_detachArrayBuffer, - "detachArrayBuffer", 1)); - JS_SetPropertyStr(ctx, obj262, "evalScript", - JS_NewCFunction(ctx, js_evalScript, - "evalScript", 1)); - JS_SetPropertyStr(ctx, obj262, "codePointRange", - JS_NewCFunction(ctx, js_string_codePointRange, - "codePointRange", 2)); -#ifdef CONFIG_AGENT - JS_SetPropertyStr(ctx, obj262, "agent", js_new_agent(ctx)); -#endif - - JS_SetPropertyStr(ctx, obj262, "global", - JS_DupValue(ctx, global_obj)); - JS_SetPropertyStr(ctx, obj262, "createRealm", - JS_NewCFunction(ctx, js_createRealm, - "createRealm", 0)); - obj = JS_NewCFunction(ctx, js_IsHTMLDDA, "IsHTMLDDA", 0); - JS_SetIsHTMLDDA(ctx, obj); - JS_SetPropertyStr(ctx, obj262, "IsHTMLDDA", obj); - - JS_SetPropertyStr(ctx, global_obj, "$262", JS_DupValue(ctx, obj262)); - - JS_FreeValue(ctx, global_obj); - return obj262; -} - -static void add_helpers(JSContext *ctx) -{ - JS_FreeValue(ctx, add_helpers1(ctx)); -} - -static char *load_file(const char *filename, size_t *lenp) -{ - char *buf; - size_t buf_len; - buf = (char *)js_load_file(NULL, &buf_len, filename); - if (!buf) - perror_exit(1, filename); - if (lenp) - *lenp = buf_len; - return buf; -} - -static JSModuleDef *js_module_loader_test(JSContext *ctx, - const char *module_name, void *opaque) -{ - size_t buf_len; - uint8_t *buf; - JSModuleDef *m; - JSValue func_val; - - buf = js_load_file(ctx, &buf_len, module_name); - if (!buf) { - JS_ThrowReferenceError(ctx, "could not load module filename '%s'", - module_name); - return NULL; - } - - /* compile the module */ - func_val = JS_Eval(ctx, (char *)buf, buf_len, module_name, - JS_EVAL_TYPE_MODULE | JS_EVAL_FLAG_COMPILE_ONLY); - js_free(ctx, buf); - if (JS_IsException(func_val)) - return NULL; - /* the module is already referenced, so we must free it */ - m = JS_VALUE_GET_PTR(func_val); - JS_FreeValue(ctx, func_val); - return m; -} - -int is_line_sep(char c) -{ - return (c == '\0' || c == '\n' || c == '\r'); -} - -char *find_line(const char *str, const char *line) -{ - if (str) { - const char *p; - int len = strlen(line); - for (p = str; (p = strstr(p, line)) != NULL; p += len + 1) { - if ((p == str || is_line_sep(p[-1])) && is_line_sep(p[len])) - return (char *)p; - } - } - return NULL; -} - -int is_word_sep(char c) -{ - return (c == '\0' || isspace((unsigned char)c) || c == ','); -} - -char *find_word(const char *str, const char *word) -{ - const char *p; - int len = strlen(word); - if (str && len) { - for (p = str; (p = strstr(p, word)) != NULL; p += len) { - if ((p == str || is_word_sep(p[-1])) && is_word_sep(p[len])) - return (char *)p; - } - } - return NULL; -} - -/* handle exclude directories */ -void update_exclude_dirs(void) -{ - namelist_t *lp = &test_list; - namelist_t *ep = &exclude_list; - namelist_t *dp = &exclude_dir_list; - char *name; - int i, j, count; - - /* split directpries from exclude_list */ - for (count = i = 0; i < ep->count; i++) { - name = ep->array[i]; - if (has_suffix(name, "/")) { - namelist_add(dp, NULL, name); - free(name); - } else { - ep->array[count++] = name; - } - } - ep->count = count; - - namelist_sort(dp); - - /* filter out excluded directories */ - for (count = i = 0; i < lp->count; i++) { - name = lp->array[i]; - for (j = 0; j < dp->count; j++) { - if (has_prefix(name, dp->array[j])) { - test_excluded++; - free(name); - name = NULL; - break; - } - } - if (name) { - lp->array[count++] = name; - } - } - lp->count = count; -} - -void load_config(const char *filename) -{ - char buf[1024]; - FILE *f; - char *base_name; - enum { - SECTION_NONE = 0, - SECTION_CONFIG, - SECTION_EXCLUDE, - SECTION_FEATURES, - SECTION_TESTS, - } section = SECTION_NONE; - int lineno = 0; - - f = fopen(filename, "rb"); - if (!f) { - perror_exit(1, filename); - } - base_name = get_basename(filename); - - while (fgets(buf, sizeof(buf), f) != NULL) { - char *p, *q; - lineno++; - p = str_strip(buf); - if (*p == '#' || *p == ';' || *p == '\0') - continue; /* line comment */ - - if (*p == "[]"[0]) { - /* new section */ - p++; - p[strcspn(p, "]")] = '\0'; - if (str_equal(p, "config")) - section = SECTION_CONFIG; - else if (str_equal(p, "exclude")) - section = SECTION_EXCLUDE; - else if (str_equal(p, "features")) - section = SECTION_FEATURES; - else if (str_equal(p, "tests")) - section = SECTION_TESTS; - else - section = SECTION_NONE; - continue; - } - q = strchr(p, '='); - if (q) { - /* setting: name=value */ - *q++ = '\0'; - q = str_strip(q); - } - switch (section) { - case SECTION_CONFIG: - if (!q) { - printf("%s:%d: syntax error\n", filename, lineno); - continue; - } - if (str_equal(p, "style")) { - new_style = str_equal(q, "new"); - continue; - } - if (str_equal(p, "testdir")) { - char *testdir = compose_path(base_name, q); - enumerate_tests(testdir); - free(testdir); - continue; - } - if (str_equal(p, "harnessdir")) { - harness_dir = compose_path(base_name, q); - continue; - } - if (str_equal(p, "harnessexclude")) { - str_append(&harness_exclude, " ", q); - continue; - } - if (str_equal(p, "features")) { - str_append(&harness_features, " ", q); - continue; - } - if (str_equal(p, "skip-features")) { - str_append(&harness_skip_features, " ", q); - continue; - } - if (str_equal(p, "mode")) { - if (str_equal(q, "default") || str_equal(q, "default-nostrict")) - test_mode = TEST_DEFAULT_NOSTRICT; - else if (str_equal(q, "default-strict")) - test_mode = TEST_DEFAULT_STRICT; - else if (str_equal(q, "nostrict")) - test_mode = TEST_NOSTRICT; - else if (str_equal(q, "strict")) - test_mode = TEST_STRICT; - else if (str_equal(q, "all") || str_equal(q, "both")) - test_mode = TEST_ALL; - else - fatal(2, "unknown test mode: %s", q); - continue; - } - if (str_equal(p, "strict")) { - if (str_equal(q, "skip") || str_equal(q, "no")) - test_mode = TEST_NOSTRICT; - continue; - } - if (str_equal(p, "nostrict")) { - if (str_equal(q, "skip") || str_equal(q, "no")) - test_mode = TEST_STRICT; - continue; - } - if (str_equal(p, "async")) { - skip_async = !str_equal(q, "yes"); - continue; - } - if (str_equal(p, "module")) { - skip_module = !str_equal(q, "yes"); - continue; - } - if (str_equal(p, "verbose")) { - verbose = str_equal(q, "yes"); - continue; - } - if (str_equal(p, "errorfile")) { - error_filename = compose_path(base_name, q); - continue; - } - if (str_equal(p, "excludefile")) { - char *path = compose_path(base_name, q); - namelist_load(&exclude_list, path); - free(path); - continue; - } - if (str_equal(p, "reportfile")) { - report_filename = compose_path(base_name, q); - continue; - } - case SECTION_EXCLUDE: - namelist_add(&exclude_list, base_name, p); - break; - case SECTION_FEATURES: - if (!q || str_equal(q, "yes")) - str_append(&harness_features, " ", p); - else - str_append(&harness_skip_features, " ", p); - break; - case SECTION_TESTS: - namelist_add(&test_list, base_name, p); - break; - default: - /* ignore settings in other sections */ - break; - } - } - fclose(f); - free(base_name); -} - -char *find_error(const char *filename, int *pline, int is_strict) -{ - if (error_file) { - size_t len = strlen(filename); - const char *p, *q, *r; - int line; - - for (p = error_file; (p = strstr(p, filename)) != NULL; p += len) { - if ((p == error_file || p[-1] == '\n' || p[-1] == '(') && p[len] == ':') { - q = p + len; - line = 1; - if (*q == ':') { - line = strtol(q + 1, (char**)&q, 10); - if (*q == ':') - q++; - } - while (*q == ' ') { - q++; - } - /* check strict mode indicator */ - if (!strstart(q, "strict mode: ", &q) != !is_strict) - continue; - r = q = skip_prefix(q, "unexpected error: "); - r += strcspn(r, "\n"); - while (r[0] == '\n' && r[1] && strncmp(r + 1, filename, 8)) { - r++; - r += strcspn(r, "\n"); - } - if (pline) - *pline = line; - return strdup_len(q, r - q); - } - } - } - return NULL; -} - -int skip_comments(const char *str, int line, int *pline) -{ - const char *p; - int c; - - p = str; - while ((c = (unsigned char)*p++) != '\0') { - if (isspace(c)) { - if (c == '\n') - line++; - continue; - } - if (c == '/' && *p == '/') { - while (*++p && *p != '\n') - continue; - continue; - } - if (c == '/' && *p == '*') { - for (p += 1; *p; p++) { - if (*p == '\n') { - line++; - continue; - } - if (*p == '*' && p[1] == '/') { - p += 2; - break; - } - } - continue; - } - break; - } - if (pline) - *pline = line; - - return p - str; -} - -int longest_match(const char *str, const char *find, int pos, int *ppos, int line, int *pline) -{ - int len, maxlen; - - maxlen = 0; - - if (*find) { - const char *p; - for (p = str + pos; *p; p++) { - if (*p == *find) { - for (len = 1; p[len] && p[len] == find[len]; len++) - continue; - if (len > maxlen) { - maxlen = len; - if (ppos) - *ppos = p - str; - if (pline) - *pline = line; - if (!find[len]) - break; - } - } - if (*p == '\n') - line++; - } - } - return maxlen; -} - -static int eval_buf(JSContext *ctx, const char *buf, size_t buf_len, - const char *filename, int is_test, int is_negative, - const char *error_type, FILE *outfile, int eval_flags, - int is_async) -{ - JSValue res_val, exception_val; - int ret, error_line, pos, pos_line; - BOOL is_error, has_error_line; - const char *error_name; - - pos = skip_comments(buf, 1, &pos_line); - error_line = pos_line; - has_error_line = FALSE; - exception_val = JS_UNDEFINED; - error_name = NULL; - - async_done = 0; /* counter of "Test262:AsyncTestComplete" messages */ - - res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); - - if (is_async && !JS_IsException(res_val)) { - JS_FreeValue(ctx, res_val); - for(;;) { - JSContext *ctx1; - ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); - if (ret < 0) { - res_val = JS_EXCEPTION; - break; - } else if (ret == 0) { - /* test if the test called $DONE() once */ - if (async_done != 1) { - res_val = JS_ThrowTypeError(ctx, "$DONE() not called"); - } else { - res_val = JS_UNDEFINED; - } - break; - } - } - } - - if (JS_IsException(res_val)) { - exception_val = JS_GetException(ctx); - is_error = JS_IsError(ctx, exception_val); - /* XXX: should get the filename and line number */ - if (outfile) { - if (!is_error) - fprintf(outfile, "%sThrow: ", (eval_flags & JS_EVAL_FLAG_STRICT) ? - "strict mode: " : ""); - js_print(ctx, JS_NULL, 1, &exception_val); - } - if (is_error) { - JSValue name, stack; - const char *stack_str; - - name = JS_GetPropertyStr(ctx, exception_val, "name"); - error_name = JS_ToCString(ctx, name); - stack = JS_GetPropertyStr(ctx, exception_val, "stack"); - if (!JS_IsUndefined(stack)) { - stack_str = JS_ToCString(ctx, stack); - if (stack_str) { - const char *p; - int len; - - if (outfile) - fprintf(outfile, "%s", stack_str); - - len = strlen(filename); - p = strstr(stack_str, filename); - if (p != NULL && p[len] == ':') { - error_line = atoi(p + len + 1); - has_error_line = TRUE; - } - JS_FreeCString(ctx, stack_str); - } - } - JS_FreeValue(ctx, stack); - JS_FreeValue(ctx, name); - } - if (is_negative) { - ret = 0; - if (error_type) { - char *error_class; - const char *msg; - - msg = JS_ToCString(ctx, exception_val); - error_class = strdup_len(msg, strcspn(msg, ":")); - if (!str_equal(error_class, error_type)) - ret = -1; - free(error_class); - JS_FreeCString(ctx, msg); - } - } else { - ret = -1; - } - } else { - if (is_negative) - ret = -1; - else - ret = 0; - } - - if (verbose && is_test) { - JSValue msg_val = JS_UNDEFINED; - const char *msg = NULL; - int s_line; - char *s = find_error(filename, &s_line, eval_flags & JS_EVAL_FLAG_STRICT); - const char *strict_mode = (eval_flags & JS_EVAL_FLAG_STRICT) ? "strict mode: " : ""; - - if (!JS_IsUndefined(exception_val)) { - msg_val = JS_ToString(ctx, exception_val); - msg = JS_ToCString(ctx, msg_val); - } - if (is_negative) { // expect error - if (ret == 0) { - if (msg && s && - (str_equal(s, "expected error") || - strstart(s, "unexpected error type:", NULL) || - str_equal(s, msg))) { // did not have error yet - if (!has_error_line) { - longest_match(buf, msg, pos, &pos, pos_line, &error_line); - } - printf("%s:%d: %sOK, now has error %s\n", - filename, error_line, strict_mode, msg); - fixed_errors++; - } - } else { - if (!s) { // not yet reported - if (msg) { - fprintf(error_out, "%s:%d: %sunexpected error type: %s\n", - filename, error_line, strict_mode, msg); - } else { - fprintf(error_out, "%s:%d: %sexpected error\n", - filename, error_line, strict_mode); - } - new_errors++; - } - } - } else { // should not have error - if (msg) { - if (!s || !str_equal(s, msg)) { - if (!has_error_line) { - char *p = skip_prefix(msg, "Test262 Error: "); - if (strstr(p, "Test case returned non-true value!")) { - longest_match(buf, "runTestCase", pos, &pos, pos_line, &error_line); - } else { - longest_match(buf, p, pos, &pos, pos_line, &error_line); - } - } - fprintf(error_out, "%s:%d: %s%s%s\n", filename, error_line, strict_mode, - error_file ? "unexpected error: " : "", msg); - - if (s && (!str_equal(s, msg) || error_line != s_line)) { - printf("%s:%d: %sprevious error: %s\n", filename, s_line, strict_mode, s); - changed_errors++; - } else { - new_errors++; - } - } - } else { - if (s) { - printf("%s:%d: %sOK, fixed error: %s\n", filename, s_line, strict_mode, s); - fixed_errors++; - } - } - } - JS_FreeValue(ctx, msg_val); - JS_FreeCString(ctx, msg); - free(s); - } - JS_FreeCString(ctx, error_name); - JS_FreeValue(ctx, exception_val); - JS_FreeValue(ctx, res_val); - return ret; -} - -static int eval_file(JSContext *ctx, const char *base, const char *p, - int eval_flags) -{ - char *buf; - size_t buf_len; - char *filename = compose_path(base, p); - - buf = load_file(filename, &buf_len); - if (!buf) { - warning("cannot load %s", filename); - goto fail; - } - if (eval_buf(ctx, buf, buf_len, filename, FALSE, FALSE, NULL, stderr, - eval_flags, FALSE)) { - warning("error evaluating %s", filename); - goto fail; - } - free(buf); - free(filename); - return 0; - -fail: - free(buf); - free(filename); - return 1; -} - -char *extract_desc(const char *buf, char style) -{ - const char *p, *desc_start; - char *desc; - int len; - - p = buf; - while (*p != '\0') { - if (p[0] == '/' && p[1] == '*' && p[2] == style && p[3] != '/') { - p += 3; - desc_start = p; - while (*p != '\0' && (p[0] != '*' || p[1] != '/')) - p++; - if (*p == '\0') { - warning("Expecting end of desc comment"); - return NULL; - } - len = p - desc_start; - desc = malloc(len + 1); - memcpy(desc, desc_start, len); - desc[len] = '\0'; - return desc; - } else { - p++; - } - } - return NULL; -} - -static char *find_tag(char *desc, const char *tag, int *state) -{ - char *p; - p = strstr(desc, tag); - if (p) { - p += strlen(tag); - *state = 0; - } - return p; -} - -static char *get_option(char **pp, int *state) -{ - char *p, *p0, *option = NULL; - if (*pp) { - for (p = *pp;; p++) { - switch (*p) { - case '[': - *state += 1; - continue; - case ']': - *state -= 1; - if (*state > 0) - continue; - p = NULL; - break; - case ' ': - case '\t': - case '\r': - case ',': - case '-': - continue; - case '\n': - if (*state > 0 || p[1] == ' ') - continue; - p = NULL; - break; - case '\0': - p = NULL; - break; - default: - p0 = p; - p += strcspn(p0, " \t\r\n,]"); - option = strdup_len(p0, p - p0); - break; - } - break; - } - *pp = p; - } - return option; -} - -void update_stats(JSRuntime *rt, const char *filename) { - JSMemoryUsage stats; - JS_ComputeMemoryUsage(rt, &stats); - if (stats_count++ == 0) { - stats_avg = stats_all = stats_min = stats_max = stats; - stats_min_filename = strdup(filename); - stats_max_filename = strdup(filename); - } else { - if (stats_max.malloc_size < stats.malloc_size) { - stats_max = stats; - free(stats_max_filename); - stats_max_filename = strdup(filename); - } - if (stats_min.malloc_size > stats.malloc_size) { - stats_min = stats; - free(stats_min_filename); - stats_min_filename = strdup(filename); - } - -#define update(f) stats_avg.f = (stats_all.f += stats.f) / stats_count - update(malloc_count); - update(malloc_size); - update(memory_used_count); - update(memory_used_size); - update(atom_count); - update(atom_size); - update(str_count); - update(str_size); - update(obj_count); - update(obj_size); - update(prop_count); - update(prop_size); - update(shape_count); - update(shape_size); - update(js_func_count); - update(js_func_size); - update(js_func_code_size); - update(js_func_pc2line_count); - update(js_func_pc2line_size); - update(c_func_count); - update(array_count); - update(fast_array_count); - update(fast_array_elements); - } -#undef update -} - -int run_test_buf(const char *filename, char *harness, namelist_t *ip, - char *buf, size_t buf_len, const char* error_type, - int eval_flags, BOOL is_negative, BOOL is_async, - BOOL can_block) -{ - JSRuntime *rt; - JSContext *ctx; - int i, ret; - - rt = JS_NewRuntime(); - if (rt == NULL) { - fatal(1, "JS_NewRuntime failure"); - } - ctx = JS_NewContext(rt); - if (ctx == NULL) { - JS_FreeRuntime(rt); - fatal(1, "JS_NewContext failure"); - } - JS_SetRuntimeInfo(rt, filename); - - JS_SetCanBlock(rt, can_block); - - /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, NULL); - - add_helpers(ctx); - - for (i = 0; i < ip->count; i++) { - if (eval_file(ctx, harness, ip->array[i], - JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_STRIP)) { - fatal(1, "error including %s for %s", ip->array[i], filename); - } - } - - ret = eval_buf(ctx, buf, buf_len, filename, TRUE, is_negative, - error_type, outfile, eval_flags, is_async); - ret = (ret != 0); - - if (dump_memory) { - update_stats(rt, filename); - } -#ifdef CONFIG_AGENT - js_agent_free(ctx); -#endif - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - - test_count++; - if (ret) { - test_failed++; - if (outfile) { - /* do not output a failure number to minimize diff */ - fprintf(outfile, " FAILED\n"); - } - } - return ret; -} - -int run_test(const char *filename, int index) -{ - char harnessbuf[1024]; - char *harness; - char *buf; - size_t buf_len; - char *desc, *p; - char *error_type; - int ret, eval_flags, use_strict, use_nostrict; - BOOL is_negative, is_nostrict, is_onlystrict, is_async, is_module, skip; - BOOL can_block; - namelist_t include_list = { 0 }, *ip = &include_list; - - is_nostrict = is_onlystrict = is_negative = is_async = is_module = skip = FALSE; - can_block = TRUE; - error_type = NULL; - buf = load_file(filename, &buf_len); - - harness = harness_dir; - - if (new_style) { - if (!harness) { - p = strstr(filename, "test/"); - if (p) { - snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s", - (int)(p - filename), filename, "harness"); - } - harness = harnessbuf; - } - namelist_add(ip, NULL, "sta.js"); - namelist_add(ip, NULL, "assert.js"); - /* extract the YAML frontmatter */ - desc = extract_desc(buf, '-'); - if (desc) { - char *ifile, *option; - int state; - p = find_tag(desc, "includes:", &state); - if (p) { - while ((ifile = get_option(&p, &state)) != NULL) { - // skip unsupported harness files - if (find_word(harness_exclude, ifile)) { - skip |= 1; - } else { - namelist_add(ip, NULL, ifile); - } - free(ifile); - } - } - p = find_tag(desc, "flags:", &state); - if (p) { - while ((option = get_option(&p, &state)) != NULL) { - if (str_equal(option, "noStrict") || - str_equal(option, "raw")) { - is_nostrict = TRUE; - skip |= (test_mode == TEST_STRICT); - } - else if (str_equal(option, "onlyStrict")) { - is_onlystrict = TRUE; - skip |= (test_mode == TEST_NOSTRICT); - } - else if (str_equal(option, "async")) { - is_async = TRUE; - skip |= skip_async; - } - else if (str_equal(option, "module")) { - is_module = TRUE; - skip |= skip_module; - } - else if (str_equal(option, "CanBlockIsFalse")) { - can_block = FALSE; - } - free(option); - } - } - p = find_tag(desc, "negative:", &state); - if (p) { - /* XXX: should extract the phase */ - char *q = find_tag(p, "type:", &state); - if (q) { - while (isspace(*q)) - q++; - error_type = strdup_len(q, strcspn(q, " \n")); - } - is_negative = TRUE; - } - p = find_tag(desc, "features:", &state); - if (p) { - while ((option = get_option(&p, &state)) != NULL) { - if (find_word(harness_features, option)) { - /* feature is enabled */ - } else if (find_word(harness_skip_features, option)) { - /* skip disabled feature */ - skip |= 1; - } else { - /* feature is not listed: skip and warn */ - printf("%s:%d: unknown feature: %s\n", filename, 1, option); - skip |= 1; - } - free(option); - } - } - free(desc); - } - if (is_async) - namelist_add(ip, NULL, "doneprintHandle.js"); - } else { - char *ifile; - - if (!harness) { - p = strstr(filename, "test/"); - if (p) { - snprintf(harnessbuf, sizeof(harnessbuf), "%.*s%s", - (int)(p - filename), filename, "test/harness"); - } - harness = harnessbuf; - } - - namelist_add(ip, NULL, "sta.js"); - - /* include extra harness files */ - for (p = buf; (p = strstr(p, "$INCLUDE(\"")) != NULL; p++) { - p += 10; - ifile = strdup_len(p, strcspn(p, "\"")); - // skip unsupported harness files - if (find_word(harness_exclude, ifile)) { - skip |= 1; - } else { - namelist_add(ip, NULL, ifile); - } - free(ifile); - } - - /* locate the old style configuration comment */ - desc = extract_desc(buf, '*'); - if (desc) { - if (strstr(desc, "@noStrict")) { - is_nostrict = TRUE; - skip |= (test_mode == TEST_STRICT); - } - if (strstr(desc, "@onlyStrict")) { - is_onlystrict = TRUE; - skip |= (test_mode == TEST_NOSTRICT); - } - if (strstr(desc, "@negative")) { - /* XXX: should extract the regex to check error type */ - is_negative = TRUE; - } - free(desc); - } - } - - if (outfile && index >= 0) { - fprintf(outfile, "%d: %s%s%s%s%s%s%s\n", index, filename, - is_nostrict ? " @noStrict" : "", - is_onlystrict ? " @onlyStrict" : "", - is_async ? " async" : "", - is_module ? " module" : "", - is_negative ? " @negative" : "", - skip ? " SKIPPED" : ""); - fflush(outfile); - } - - use_strict = use_nostrict = 0; - /* XXX: should remove 'test_mode' or simplify it just to force - strict or non strict mode for single file tests */ - switch (test_mode) { - case TEST_DEFAULT_NOSTRICT: - if (is_onlystrict) - use_strict = 1; - else - use_nostrict = 1; - break; - case TEST_DEFAULT_STRICT: - if (is_nostrict) - use_nostrict = 1; - else - use_strict = 1; - break; - case TEST_NOSTRICT: - if (!is_onlystrict) - use_nostrict = 1; - break; - case TEST_STRICT: - if (!is_nostrict) - use_strict = 1; - break; - case TEST_ALL: - if (is_module) { - use_nostrict = 1; - } else { - if (!is_nostrict) - use_strict = 1; - if (!is_onlystrict) - use_nostrict = 1; - } - break; - } - - if (skip || use_strict + use_nostrict == 0) { - test_skipped++; - ret = -2; - } else { - clock_t clocks; - - if (is_module) { - eval_flags = JS_EVAL_TYPE_MODULE; - } else { - eval_flags = JS_EVAL_TYPE_GLOBAL; - } - clocks = clock(); - ret = 0; - if (use_nostrict) { - ret = run_test_buf(filename, harness, ip, buf, buf_len, - error_type, eval_flags, is_negative, is_async, - can_block); - } - if (use_strict) { - ret |= run_test_buf(filename, harness, ip, buf, buf_len, - error_type, eval_flags | JS_EVAL_FLAG_STRICT, - is_negative, is_async, can_block); - } - clocks = clock() - clocks; - if (outfile && index >= 0 && clocks >= CLOCKS_PER_SEC / 10) { - /* output timings for tests that take more than 100 ms */ - fprintf(outfile, " time: %d ms\n", (int)(clocks * 1000LL / CLOCKS_PER_SEC)); - } - } - namelist_free(&include_list); - free(error_type); - free(buf); - - return ret; -} - -/* run a test when called by test262-harness+eshost */ -int run_test262_harness_test(const char *filename, BOOL is_module) -{ - JSRuntime *rt; - JSContext *ctx; - char *buf; - size_t buf_len; - int eval_flags, ret_code, ret; - JSValue res_val; - BOOL can_block; - - outfile = stdout; /* for js_print */ - - rt = JS_NewRuntime(); - if (rt == NULL) { - fatal(1, "JS_NewRuntime failure"); - } - ctx = JS_NewContext(rt); - if (ctx == NULL) { - JS_FreeRuntime(rt); - fatal(1, "JS_NewContext failure"); - } - JS_SetRuntimeInfo(rt, filename); - - can_block = TRUE; - JS_SetCanBlock(rt, can_block); - - /* loader for ES6 modules */ - JS_SetModuleLoaderFunc(rt, NULL, js_module_loader_test, NULL); - - add_helpers(ctx); - - buf = load_file(filename, &buf_len); - - if (is_module) { - eval_flags = JS_EVAL_TYPE_MODULE; - } else { - eval_flags = JS_EVAL_TYPE_GLOBAL; - } - res_val = JS_Eval(ctx, buf, buf_len, filename, eval_flags); - ret_code = 0; - if (JS_IsException(res_val)) { - js_std_dump_error(ctx); - ret_code = 1; - } else { - JS_FreeValue(ctx, res_val); - for(;;) { - JSContext *ctx1; - ret = JS_ExecutePendingJob(JS_GetRuntime(ctx), &ctx1); - if (ret < 0) { - js_std_dump_error(ctx1); - ret_code = 1; - } else if (ret == 0) { - break; - } - } - } - free(buf); -#ifdef CONFIG_AGENT - js_agent_free(ctx); -#endif - JS_FreeContext(ctx); - JS_FreeRuntime(rt); - return ret_code; -} - -clock_t last_clock; - -void show_progress(int force) { - clock_t t = clock(); - if (force || !last_clock || (t - last_clock) > CLOCKS_PER_SEC / 20) { - last_clock = t; - /* output progress indicator: erase end of line and return to col 0 */ - fprintf(stderr, "%d/%d/%d\033[K\r", - test_failed, test_count, test_skipped); - fflush(stderr); - } -} - -static int slow_test_threshold; - -void run_test_dir_list(namelist_t *lp, int start_index, int stop_index) -{ - int i; - - namelist_sort(lp); - for (i = 0; i < lp->count; i++) { - const char *p = lp->array[i]; - if (namelist_find(&exclude_list, p) >= 0) { - test_excluded++; - } else if (test_index < start_index) { - test_skipped++; - } else if (stop_index >= 0 && test_index > stop_index) { - test_skipped++; - } else { - int ti; - if (slow_test_threshold != 0) { - ti = get_clock_ms(); - } else { - ti = 0; - } - run_test(p, test_index); - if (slow_test_threshold != 0) { - ti = get_clock_ms() - ti; - if (ti >= slow_test_threshold) - fprintf(stderr, "\n%s (%d ms)\n", p, ti); - } - show_progress(FALSE); - } - test_index++; - } - show_progress(TRUE); -} - -void help(void) -{ - printf("run-test262 version " CONFIG_VERSION "\n" - "usage: run-test262 [options] {-f file ... | [dir_list] [index range]}\n" - "-h help\n" - "-a run tests in strict and nostrict modes\n" - "-m print memory usage summary\n" - "-n use new style harness\n" - "-N run test prepared by test262-harness+eshost\n" - "-s run tests in strict mode, skip @nostrict tests\n" - "-E only run tests from the error file\n" - "-u update error file\n" - "-v verbose: output error messages\n" - "-T duration display tests taking more than 'duration' ms\n" - "-c file read configuration from 'file'\n" - "-d dir run all test files in directory tree 'dir'\n" - "-e file load the known errors from 'file'\n" - "-f file execute single test from 'file'\n" - "-r file set the report file name (default=none)\n" - "-x file exclude tests listed in 'file'\n"); - exit(1); -} - -char *get_opt_arg(const char *option, char *arg) -{ - if (!arg) { - fatal(2, "missing argument for option %s", option); - } - return arg; -} - -int main(int argc, char **argv) -{ - int optind, start_index, stop_index; - BOOL is_dir_list; - BOOL only_check_errors = FALSE; - const char *filename; - BOOL is_test262_harness = FALSE; - BOOL is_module = FALSE; - -#if !defined(_WIN32) - /* Date tests assume California local time */ - setenv("TZ", "America/Los_Angeles", 1); -#endif - - /* cannot use getopt because we want to pass the command line to - the script */ - optind = 1; - is_dir_list = TRUE; - while (optind < argc) { - char *arg = argv[optind]; - if (*arg != '-') - break; - optind++; - if (str_equal(arg, "-h")) { - help(); - } else if (str_equal(arg, "-m")) { - dump_memory++; - } else if (str_equal(arg, "-n")) { - new_style++; - } else if (str_equal(arg, "-s")) { - test_mode = TEST_STRICT; - } else if (str_equal(arg, "-a")) { - test_mode = TEST_ALL; - } else if (str_equal(arg, "-u")) { - update_errors++; - } else if (str_equal(arg, "-v")) { - verbose++; - } else if (str_equal(arg, "-c")) { - load_config(get_opt_arg(arg, argv[optind++])); - } else if (str_equal(arg, "-d")) { - enumerate_tests(get_opt_arg(arg, argv[optind++])); - } else if (str_equal(arg, "-e")) { - error_filename = get_opt_arg(arg, argv[optind++]); - } else if (str_equal(arg, "-x")) { - namelist_load(&exclude_list, get_opt_arg(arg, argv[optind++])); - } else if (str_equal(arg, "-f")) { - is_dir_list = FALSE; - } else if (str_equal(arg, "-r")) { - report_filename = get_opt_arg(arg, argv[optind++]); - } else if (str_equal(arg, "-E")) { - only_check_errors = TRUE; - } else if (str_equal(arg, "-T")) { - slow_test_threshold = atoi(get_opt_arg(arg, argv[optind++])); - } else if (str_equal(arg, "-N")) { - is_test262_harness = TRUE; - } else if (str_equal(arg, "--module")) { - is_module = TRUE; - } else { - fatal(1, "unknown option: %s", arg); - break; - } - } - - if (optind >= argc && !test_list.count) - help(); - - if (is_test262_harness) { - return run_test262_harness_test(argv[optind], is_module); - } - - error_out = stdout; - if (error_filename) { - error_file = load_file(error_filename, NULL); - if (only_check_errors && error_file) { - namelist_free(&test_list); - namelist_add_from_error_file(&test_list, error_file); - } - if (update_errors) { - free(error_file); - error_file = NULL; - error_out = fopen(error_filename, "w"); - if (!error_out) { - perror_exit(1, error_filename); - } - } - } - - update_exclude_dirs(); - - if (is_dir_list) { - if (optind < argc && !isdigit(argv[optind][0])) { - filename = argv[optind++]; - namelist_load(&test_list, filename); - } - start_index = 0; - stop_index = -1; - if (optind < argc) { - start_index = atoi(argv[optind++]); - if (optind < argc) { - stop_index = atoi(argv[optind++]); - } - } - if (!report_filename || str_equal(report_filename, "none")) { - outfile = NULL; - } else if (str_equal(report_filename, "-")) { - outfile = stdout; - } else { - outfile = fopen(report_filename, "wb"); - if (!outfile) { - perror_exit(1, report_filename); - } - } - run_test_dir_list(&test_list, start_index, stop_index); - - if (outfile && outfile != stdout) { - fclose(outfile); - outfile = NULL; - } - } else { - outfile = stdout; - while (optind < argc) { - run_test(argv[optind++], -1); - } - } - - if (dump_memory) { - if (dump_memory > 1 && stats_count > 1) { - printf("\nMininum memory statistics for %s:\n\n", stats_min_filename); - JS_DumpMemoryUsage(stdout, &stats_min, NULL); - printf("\nMaximum memory statistics for %s:\n\n", stats_max_filename); - JS_DumpMemoryUsage(stdout, &stats_max, NULL); - } - printf("\nAverage memory statistics for %d tests:\n\n", stats_count); - JS_DumpMemoryUsage(stdout, &stats_avg, NULL); - printf("\n"); - } - - if (is_dir_list) { - fprintf(stderr, "Result: %d/%d error%s", - test_failed, test_count, test_count != 1 ? "s" : ""); - if (test_excluded) - fprintf(stderr, ", %d excluded", test_excluded); - if (test_skipped) - fprintf(stderr, ", %d skipped", test_skipped); - if (error_file) { - if (new_errors) - fprintf(stderr, ", %d new", new_errors); - if (changed_errors) - fprintf(stderr, ", %d changed", changed_errors); - if (fixed_errors) - fprintf(stderr, ", %d fixed", fixed_errors); - } - fprintf(stderr, "\n"); - } - - if (error_out && error_out != stdout) { - fclose(error_out); - error_out = NULL; - } - - namelist_free(&test_list); - namelist_free(&exclude_list); - namelist_free(&exclude_dir_list); - free(harness_dir); - free(harness_features); - free(harness_exclude); - free(error_file); - - return 0; -} diff --git a/quickjs/test262.conf b/quickjs/test262.conf deleted file mode 100644 index bb66cf4..0000000 --- a/quickjs/test262.conf +++ /dev/null @@ -1,209 +0,0 @@ -[config] -# general settings for test262 ES6 version - -# framework style: old, new -style=new - -# handle tests tagged as [noStrict]: yes, no, skip -nostrict=yes - -# handle tests tagged as [strictOnly]: yes, no, skip -strict=yes - -# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all -mode=default - -# handle tests flagged as [async]: yes, no, skip -# for these, load 'harness/doneprintHandle.js' prior to test -# and expect `print('Test262:AsyncTestComplete')` to be called for -# successful termination -async=yes - -# handle tests flagged as [module]: yes, no, skip -module=yes - -# output error messages: yes, no -verbose=yes - -# load harness files from this directory -harnessdir=test262/harness - -# names of harness include files to skip -#harnessexclude= - -# name of the error file for known errors -errorfile=test262_errors.txt - -# exclude tests enumerated in this file (see also [exclude] section) -#excludefile=test262_exclude.txt - -# report test results to this file -reportfile=test262_report.txt - -# enumerate tests from this directory -testdir=test262/test - -[features] -# Standard language features and proposed extensions -# list the features that are included -# skipped features are tagged as such to avoid warnings - -AggregateError -align-detached-buffer-semantics-with-web-reality -arbitrary-module-namespace-names=skip -array-find-from-last=skip -Array.prototype.at=skip -Array.prototype.flat -Array.prototype.flatMap -Array.prototype.flatten -Array.prototype.values -ArrayBuffer -arrow-function -async-functions -async-iteration -Atomics -Atomics.waitAsync=skip -BigInt -caller -class -class-fields-private -class-fields-private-in=skip -class-fields-public -class-methods-private -class-static-block=skip -class-static-fields-public -class-static-fields-private -class-static-methods-private -cleanupSome=skip -coalesce-expression -computed-property-names -const -cross-realm -DataView -DataView.prototype.getFloat32 -DataView.prototype.getFloat64 -DataView.prototype.getInt16 -DataView.prototype.getInt32 -DataView.prototype.getInt8 -DataView.prototype.getUint16 -DataView.prototype.getUint32 -DataView.prototype.setUint8 -default-parameters -destructuring-assignment -destructuring-binding -dynamic-import -error-cause=skip -export-star-as-namespace-from-module -FinalizationGroup=skip -FinalizationRegistry=skip -FinalizationRegistry.prototype.cleanupSome=skip -Float32Array -Float64Array -for-in-order -for-of -generators -globalThis -hashbang -host-gc-required=skip -import.meta -import-assertions=skip -Int16Array -Int32Array -Int8Array -IsHTMLDDA -json-modules=skip -json-superset -legacy-regexp=skip -let -logical-assignment-operators -Map -new.target -numeric-separator-literal -object-rest -object-spread -Object.fromEntries -Object.hasOwn -Object.is -optional-catch-binding -optional-chaining -Promise -Promise.allSettled -Promise.any -Promise.prototype.finally -Proxy -proxy-missing-checks -Reflect -Reflect.construct -Reflect.set -Reflect.setPrototypeOf -regexp-dotall -regexp-lookbehind -regexp-match-indices=skip -regexp-named-groups -regexp-unicode-property-escapes -resizable-arraybuffer=skip -rest-parameters -Set -ShadowRealm=skip -SharedArrayBuffer -string-trimming -String.fromCodePoint -String.prototype.endsWith -String.prototype.includes -String.prototype.at=skip -String.prototype.matchAll -String.prototype.replaceAll -String.prototype.trimEnd -String.prototype.trimStart -super -Symbol -Symbol.asyncIterator -Symbol.hasInstance -Symbol.isConcatSpreadable -Symbol.iterator -Symbol.match -Symbol.matchAll -Symbol.prototype.description -Symbol.replace -Symbol.search -Symbol.species -Symbol.split -Symbol.toPrimitive -Symbol.toStringTag -Symbol.unscopables -tail-call-optimization=skip -template -Temporal=skip -top-level-await=skip -TypedArray -TypedArray.prototype.at=skip -u180e -Uint16Array -Uint32Array -Uint8Array -Uint8ClampedArray -WeakMap -WeakRef=skip -WeakSet -well-formed-json-stringify -__getter__ -__proto__ -__setter__ - -[exclude] -# list excluded tests and directories here - -# intl not supported -test262/test/intl402/ - -# incompatible with the "caller" feature -test262/test/built-ins/Function/prototype/restricted-property-caller.js -test262/test/built-ins/Function/prototype/restricted-property-arguments.js -test262/test/built-ins/ThrowTypeError/unique-per-realm-function-proto.js - -# slow tests -#test262/test/built-ins/RegExp/CharacterClassEscapes/ -#test262/test/built-ins/RegExp/property-escapes/ - -[tests] -# list test files or use config.testdir diff --git a/quickjs/test262_errors.txt b/quickjs/test262_errors.txt deleted file mode 100644 index b7f6aef..0000000 --- a/quickjs/test262_errors.txt +++ /dev/null @@ -1,35 +0,0 @@ -test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: Test262Error: Expected a ReferenceError but got a ReferenceError -test262/test/built-ins/Function/internals/Construct/derived-this-uninitialized-realm.js:20: strict mode: Test262Error: Expected a ReferenceError but got a ReferenceError -test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: SyntaxError: invalid group name -test262/test/built-ins/RegExp/named-groups/non-unicode-property-names-valid.js:46: strict mode: SyntaxError: invalid group name -test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:46: Test262Error: (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/BigInt/detached-buffer.js:46: strict mode: Test262Error: (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:47: Test262Error: (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/DefineOwnProperty/detached-buffer.js:47: strict mode: Test262Error: (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer-realm.js:37: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer.js:34: TypeError: cannot convert bigint to number (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/detached-buffer.js:32: strict mode: TypeError: out-of-bound numeric index (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-minus-zero.js:20: Test262Error: Reflect.set("new TA([42n])", "-0", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-minus-zero.js:20: strict mode: Test262Error: Reflect.set("new TA([42n])", "-0", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-not-integer.js:21: Test262Error: Reflect.set("new TA([42n])", "1.1", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-not-integer.js:21: strict mode: Test262Error: Reflect.set("new TA([42n])", "1.1", 1n) must return true Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-out-of-bounds.js:27: Test262Error: Reflect.set("new TA([42n])", "-1", 1n) must return false Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/key-is-out-of-bounds.js:27: strict mode: Test262Error: Reflect.set("new TA([42n])", "-1", 1n) must return false Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/tonumber-value-detached-buffer.js:24: Test262Error: Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/BigInt/tonumber-value-detached-buffer.js:24: strict mode: Test262Error: Expected SameValue(«false», «true») to be true (Testing with BigInt64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer-realm.js:37: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/detached-buffer.js:32: strict mode: TypeError: out-of-bound numeric index (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-minus-zero.js:22: Test262Error: Reflect.set(sample, "-0", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-minus-zero.js:22: strict mode: Test262Error: Reflect.set(sample, "-0", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-not-integer.js:22: Test262Error: Reflect.set(sample, "1.1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-not-integer.js:22: strict mode: Test262Error: Reflect.set(sample, "1.1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds.js:22: Test262Error: Reflect.set(sample, "-1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/key-is-out-of-bounds.js:22: strict mode: Test262Error: Reflect.set(sample, "-1", 1) must return true Expected SameValue(«false», «true») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-detached-buffer.js:39: Test262Error: Expected SameValue(«false», «true») to be true (Testing with Float64Array.) -test262/test/built-ins/TypedArrayConstructors/internals/Set/tonumber-value-detached-buffer.js:39: strict mode: Test262Error: Expected SameValue(«false», «true») to be true (Testing with Float64Array.) -test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: TypeError: $DONE() not called -test262/test/language/expressions/dynamic-import/usage-from-eval.js:26: strict mode: TypeError: $DONE() not called -test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:21: TypeError: cannot read property 'c' of undefined -test262/test/language/expressions/optional-chaining/optional-call-preserves-this.js:15: strict mode: TypeError: cannot read property '_b' of undefined -test262/test/language/statements/for-of/head-lhs-async-invalid.js:14: unexpected error type: Test262: This statement should not be evaluated. -test262/test/language/statements/for-of/head-lhs-async-invalid.js:14: strict mode: unexpected error type: Test262: This statement should not be evaluated. diff --git a/quickjs/test262o.conf b/quickjs/test262o.conf deleted file mode 100644 index 669dead..0000000 --- a/quickjs/test262o.conf +++ /dev/null @@ -1,410 +0,0 @@ -[config] -# general settings for test262 ES5 version - -# framework style: old, new -style=old - -# handle tests tagged as @noStrict: yes, no, skip -nostrict=yes - -# handle tests tagged as @strictOnly: yes, no, skip -strict=yes - -# test mode: default, default-nostrict, default-strict, strict, nostrict, both, all -mode=default - -# output error messages: yes, no -verbose=yes - -# load harness files this directory -harnessdir=test262o/test/harness - -# name of the error file for known errors -errorfile=test262o_errors.txt - -# exclude tests enumerated in this file -#excludefile=test262o_excluded.txt - -# report test results to this file -reportfile=test262o_report.txt - -# enumerate tests from this directory -testdir=test262o/test/suite - -[exclude] -# list excluded tests and directories here - -# intl not supported -test262o/test/suite/intl402/ - -# ES6 != ES5: block scoped function definitions allowed in strict mode -test262o/test/suite/bestPractice/Sbp_A1_T1.js -test262o/test/suite/bestPractice/Sbp_A2_T1.js -test262o/test/suite/bestPractice/Sbp_A2_T2.js -test262o/test/suite/bestPractice/Sbp_A3_T1.js -test262o/test/suite/bestPractice/Sbp_A3_T2.js -test262o/test/suite/bestPractice/Sbp_A4_T1.js -test262o/test/suite/bestPractice/Sbp_A4_T2.js -test262o/test/suite/bestPractice/Sbp_A5_T2.js - -# ES6 != ES5: `y={x};` is shorthand for `y={x:x}` -test262o/test/suite/ch12/12.1/S12.1_A4_T2.js -test262o/test/suite/ch12/12.6/12.6.4/S12.6.4_A15.js - -# ES6 != ES5: function length property is configurable -test262o/test/suite/ch11/11.4/11.4.1/11.4.1-5-a-28-s.js -test262o/test/suite/ch13/13.2/13.2-15-1.js -test262o/test/suite/ch15/15.1/15.1.2/15.1.2.1/S15.1.2.1_A4.2.js -test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A9.2.js -test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A7.2.js -test262o/test/suite/ch15/15.1/15.1.2/15.1.2.4/S15.1.2.4_A2.2.js -test262o/test/suite/ch15/15.1/15.1.2/15.1.2.5/S15.1.2.5_A2.2.js -test262o/test/suite/ch15/15.1/15.1.3/15.1.3.1/S15.1.3.1_A5.2.js -test262o/test/suite/ch15/15.1/15.1.3/15.1.3.2/S15.1.3.2_A5.2.js -test262o/test/suite/ch15/15.1/15.1.3/15.1.3.3/S15.1.3.3_A5.2.js -test262o/test/suite/ch15/15.1/15.1.3/15.1.3.4/S15.1.3.4_A5.2.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-186.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-187.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-191.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-194.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-201.js -test262o/test/suite/ch15/15.2/15.2.4/15.2.4.2/S15.2.4.2_A9.js -test262o/test/suite/ch15/15.2/15.2.4/15.2.4.3/S15.2.4.3_A9.js -test262o/test/suite/ch15/15.2/15.2.4/15.2.4.4/S15.2.4.4_A9.js -test262o/test/suite/ch15/15.2/15.2.4/15.2.4.5/S15.2.4.5_A9.js -test262o/test/suite/ch15/15.2/15.2.4/15.2.4.6/S15.2.4.6_A9.js -test262o/test/suite/ch15/15.2/15.2.4/15.2.4.7/S15.2.4.7_A9.js -test262o/test/suite/ch15/15.3/15.3.3/15.3.3.2/15.3.3.2-1.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.2/S15.3.4.2_A9.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.3/S15.3.4.3_A9.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.4/S15.3.4.4_A9.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-15-2.js -test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T1.js -test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T2.js -test262o/test/suite/ch15/15.3/15.3.5/S15.3.5.1_A2_T3.js -test262o/test/suite/ch15/15.4/15.4.3/S15.4.3_A2.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.2/S15.4.4.2_A4.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.3/S15.4.4.3_A4.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.4/S15.4.4.4_A4.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A6.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A5.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A6.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A5.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A5.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A5.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A7.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A5.2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A5.2.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.4/S15.5.4.4_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.5/S15.5.4.5_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.6/S15.5.4.6_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.7/S15.5.4.7_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.8/S15.5.4.8_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.9/S15.5.4.9_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.10/S15.5.4.10_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.11/S15.5.4.11_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.12/S15.5.4.12_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.13/S15.5.4.13_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.14/S15.5.4.14_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.15/S15.5.4.15_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.16/S15.5.4.16_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.17/S15.5.4.17_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.18/S15.5.4.18_A9.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.19/S15.5.4.19_A9.js -test262o/test/suite/ch15/15.9/15.9.4/15.9.4.2/S15.9.4.2_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.4/15.9.4.3/S15.9.4.3_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.1/S15.9.5.1_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.2/S15.9.5.2_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.3/S15.9.5.3_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.4/S15.9.5.4_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.5/S15.9.5.5_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.6/S15.9.5.6_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.7/S15.9.5.7_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.8/S15.9.5.8_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.9/S15.9.5.9_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.10/S15.9.5.10_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.11/S15.9.5.11_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.12/S15.9.5.12_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.13/S15.9.5.13_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.14/S15.9.5.14_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.15/S15.9.5.15_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.16/S15.9.5.16_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.17/S15.9.5.17_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.18/S15.9.5.18_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.19/S15.9.5.19_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.20/S15.9.5.20_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.21/S15.9.5.21_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.22/S15.9.5.22_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.23/S15.9.5.23_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.24/S15.9.5.24_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.25/S15.9.5.25_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.26/S15.9.5.26_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.27/S15.9.5.27_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.28/S15.9.5.28_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.29/S15.9.5.29_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.30/S15.9.5.30_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.31/S15.9.5.31_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.32/S15.9.5.32_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.33/S15.9.5.33_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.34/S15.9.5.34_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.35/S15.9.5.35_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.36/S15.9.5.36_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.37/S15.9.5.37_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.38/S15.9.5.38_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.39/S15.9.5.39_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/S15.9.5.40_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.41/S15.9.5.41_A3_T2.js -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.42/S15.9.5.42_A3_T2.js -test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A9.js -test262o/test/suite/ch15/15.10/15.10.6/15.10.6.3/S15.10.6.3_A9.js -test262o/test/suite/ch15/15.10/15.10.6/15.10.6.4/S15.10.6.4_A9.js - -# ES6 != ES5: object literals may have duplicates -test262o/test/suite/ch11/11.1/11.1.5/11.1.5-4-4-a-1-s.js -test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-1.js -test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-b-2.js -test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-1.js -test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-c-2.js -test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-1.js -test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-2.js -test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-3.js -test262o/test/suite/ch11/11.1/11.1.5/11.1.5_4-4-d-4.js - -# ES6 != ES5: Date.prototype is no longer an instance of Date -test262o/test/suite/ch15/15.9/15.9.5/15.9.5.40/15.9.5.40_1.js - -# ES6 != ES5: Object.getPrototypeOf converts argument to object -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-3.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1-4.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-1.js - -# ES6 != ES5: Object.getPrototypeOf(NativeError) -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-12.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-13.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-14.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-15.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-16.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.2/15.2.3.2-2-17.js - -# ES6 != ES5: Object.getOwnPropertyDescriptor converts argument to object -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-3.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1-4.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-1.js - -# ES6 != ES5: Object.getOwnPropertyNames converts argument to object -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-4.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1-5.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-1.js - -# ES6 != ES5: Object.seal accepts all types -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-1.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-2.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-3.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1-4.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.8/15.2.3.8-1.js - -# ES6 != ES5: Object.freeze accepts all types -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-1.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-2.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-3.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1-4.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.9/15.2.3.9-1.js - -# ES6 != ES5: Object.preventExtensions accepts all types -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-1.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-2.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-3.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1-4.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.10/15.2.3.10-1.js - -# ES6 != ES5: Object.isSealed accepts all types -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.11/15.2.3.11-1.js - -# ES6 != ES5: Object.isFrozen accepts all types -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-1.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-2.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-3.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1-4.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.12/15.2.3.12-1.js - -# ES6 != ES5: Object.isExtensible accepts all types -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-1.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-2.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-3.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1-4.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.13/15.2.3.13-1.js - -# ES6 != ES5: Object.keys converts argument to object -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-1.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-2.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.14/15.2.3.14-1-3.js - -# ES6 != ES5: source and other properties of RegExp.prototype are not own properties -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-212.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-213.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-214.js -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.3/15.2.3.3-4-215.js - -# ES6 != ES5: String numeric object properties are enumerated first -test262o/test/suite/ch15/15.2/15.2.3/15.2.3.4/15.2.3.4-4-44.js - -# ES6: new RegExp(regex, flags) is valid -test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T1.js -test262o/test/suite/ch15/15.10/15.10.3/S15.10.3.1_A2_T2.js -test262o/test/suite/ch15/15.10/15.10.4/15.10.4.1/15.10.4.1-1.js -test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T1.js -test262o/test/suite/ch15/15.10/15.10.4/S15.10.4.1_A2_T2.js - -# ES6 != ES5: RegExp.prototype.test behavior -test262o/test/suite/ch15/15.10/15.10.6/15.10.6.2/S15.10.6.2_A5_T3.js - -# ES6 != ES5: source, global, ignoreCase, multiline, lastIndex are not data properties -# of RegExp objects and RegExp.prototype is not a RegExp object -test262o/test/suite/ch15/15.10/15.10.6/15.10.6.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-1.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/15.10.7.1-2.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A8.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A9.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.1/S15.10.7.1_A10.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-1.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/15.10.7.2-2.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A8.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A9.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.2/S15.10.7.2_A10.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-1.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/15.10.7.3-2.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A8.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A9.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.3/S15.10.7.3_A10.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-1.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/15.10.7.4-2.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A8.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A9.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.4/S15.10.7.4_A10.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-1.js -test262o/test/suite/ch15/15.10/15.10.7/15.10.7.5/15.10.7.5-2.js - -# ES6 != ES5: Error.prototype is a normal object -test262o/test/suite/ch15/15.11/15.11.4/S15.11.4_A2.js - -# ES6 different ToLength() semantics -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.5/S15.4.4.5_A4_T3.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A2_T2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T1.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.6/S15.4.4.6_A3_T3.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A2_T2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T1.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.7/S15.4.4.7_A4_T3.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.8/S15.4.4.8_A3_T3.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.9/S15.4.4.9_A3_T3.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T1.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.10/S15.4.4.10_A3_T3.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.11/S15.4.4.11_A4_T3.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T1.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.12/S15.4.4.12_A3_T3.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.13/S15.4.4.13_A3_T2.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-8.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-14.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-25.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-28.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.14/15.4.4.14-3-29.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-25.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-28.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-8.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-14.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-25.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.16/15.4.4.16-3-29.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-8.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-14.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-25.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-28.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.17/15.4.4.17-3-29.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-25.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-8.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-14.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-25.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-28.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.19/15.4.4.19-3-29.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-25.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-25.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-7.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-12.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-25.js - -# ES6 different ToLength() semantics causes near infinite runtime -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-14.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.18/15.4.4.18-3-14.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.20/15.4.4.20-3-14.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.21/15.4.4.21-3-14.js -test262o/test/suite/ch15/15.4/15.4.4/15.4.4.22/15.4.4.22-3-14.js - -# ES6 arguments/caller changes -test262o/test/suite/ch10/10.6/10.6-13-b-1-s.js -test262o/test/suite/ch10/10.6/10.6-13-b-2-s.js -test262o/test/suite/ch10/10.6/10.6-13-b-3-s.js -test262o/test/suite/ch10/10.6/10.6-14-1-s.js -test262o/test/suite/ch10/10.6/10.6-14-b-1-s.js -test262o/test/suite/ch10/10.6/10.6-14-b-4-s.js -test262o/test/suite/ch13/13.2/13.2-29-s.js -test262o/test/suite/ch13/13.2/13.2-30-s.js -test262o/test/suite/ch13/13.2/13.2-31-s.js -test262o/test/suite/ch13/13.2/13.2-32-s.js -test262o/test/suite/ch13/13.2/13.2-33-s.js -test262o/test/suite/ch13/13.2/13.2-34-s.js -test262o/test/suite/ch13/13.2/13.2-35-s.js -test262o/test/suite/ch13/13.2/13.2-36-s.js -test262o/test/suite/ch13/13.2/S13.2.3_A1.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-1.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-4.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-20-5.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-1.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-4.js -test262o/test/suite/ch15/15.3/15.3.4/15.3.4.5/15.3.4.5-21-5.js - -# u180e is no longer considered as a space -test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A2.js -test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T1.js -test262o/test/suite/ch09/9.3/9.3.1/S9.3.1_A3_T2.js -test262o/test/suite/ch15/15.1/15.1.2/15.1.2.2/S15.1.2.2_A2_T10.js -test262o/test/suite/ch15/15.1/15.1.2/15.1.2.3/S15.1.2.3_A2_T10.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-2.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-3.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-4.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-5.js -test262o/test/suite/ch15/15.5/15.5.4/15.5.4.20/15.5.4.20-3-6.js -test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A1_T1.js -test262o/test/suite/ch15/15.10/15.10.2/15.10.2.12/S15.10.2.12_A2_T1.js - -# E6 eval return value is different -test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.js -test262o/test/suite/ch12/12.6/12.6.3/S12.6.3_A9.1.js - -# ECMA 2019 optional-catch-binding feature allows try{}catch{} -test262o/test/suite/ch12/12.14/S12.14_A16_T4.js - -# Syntax error instead of ReferenceError in ES2020 -test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-1.js -test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-2.js -test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-3.js -test262o/test/suite/ch11/11.13/11.13.1/11.13.1-1-4.js - -[tests] -# list test files or use config.testdir diff --git a/quickjs/test262o_errors.txt b/quickjs/test262o_errors.txt deleted file mode 100644 index e69de29..0000000 diff --git a/quickjs/tests/bjson.c b/quickjs/tests/bjson.c deleted file mode 100644 index 8e52741..0000000 --- a/quickjs/tests/bjson.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * QuickJS: binary JSON module (test only) - * - * Copyright (c) 2017-2019 Fabrice Bellard - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -#include "../quickjs-libc.h" -#include "../cutils.h" - -static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - uint8_t *buf; - uint64_t pos, len; - JSValue obj; - size_t size; - int flags; - - if (JS_ToIndex(ctx, &pos, argv[1])) - return JS_EXCEPTION; - if (JS_ToIndex(ctx, &len, argv[2])) - return JS_EXCEPTION; - buf = JS_GetArrayBuffer(ctx, &size, argv[0]); - if (!buf) - return JS_EXCEPTION; - if (pos + len > size) - return JS_ThrowRangeError(ctx, "array buffer overflow"); - flags = 0; - if (JS_ToBool(ctx, argv[3])) - flags |= JS_READ_OBJ_REFERENCE; - obj = JS_ReadObject(ctx, buf + pos, len, flags); - return obj; -} - -static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - size_t len; - uint8_t *buf; - JSValue array; - int flags; - - flags = 0; - if (JS_ToBool(ctx, argv[1])) - flags |= JS_WRITE_OBJ_REFERENCE; - buf = JS_WriteObject(ctx, &len, argv[0], flags); - if (!buf) - return JS_EXCEPTION; - array = JS_NewArrayBufferCopy(ctx, buf, len); - js_free(ctx, buf); - return array; -} - -static const JSCFunctionListEntry js_bjson_funcs[] = { - JS_CFUNC_DEF("read", 4, js_bjson_read ), - JS_CFUNC_DEF("write", 2, js_bjson_write ), -}; - -static int js_bjson_init(JSContext *ctx, JSModuleDef *m) -{ - return JS_SetModuleExportList(ctx, m, js_bjson_funcs, - countof(js_bjson_funcs)); -} - -#ifdef JS_SHARED_LIBRARY -#define JS_INIT_MODULE js_init_module -#else -#define JS_INIT_MODULE js_init_module_bjson -#endif - -JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name) -{ - JSModuleDef *m; - m = JS_NewCModule(ctx, module_name, js_bjson_init); - if (!m) - return NULL; - JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs)); - return m; -} diff --git a/quickjs/tests/microbench.js b/quickjs/tests/microbench.js deleted file mode 100644 index 1c5f52d..0000000 --- a/quickjs/tests/microbench.js +++ /dev/null @@ -1,1065 +0,0 @@ -/* - * Javascript Micro benchmark - * - * Copyright (c) 2017-2019 Fabrice Bellard - * Copyright (c) 2017-2019 Charlie Gordon - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ -import * as std from "std"; - -function pad(str, n) { - str += ""; - while (str.length < n) - str += " "; - return str; -} - -function pad_left(str, n) { - str += ""; - while (str.length < n) - str = " " + str; - return str; -} - -function pad_center(str, n) { - str += ""; - while (str.length < n) { - if ((n - str.length) & 1) - str = str + " "; - else - str = " " + str; - } - return str; -} - -function toPrec(n, prec) { - var i, s; - for (i = 0; i < prec; i++) - n *= 10; - s = "" + Math.round(n); - for (i = s.length - prec; i <= 0; i++) - s = "0" + s; - if (prec > 0) - s = s.substring(0, i) + "." + s.substring(i); - return s; -} - -var ref_data; -var log_data; - -var heads = [ "TEST", "N", "TIME (ns)", "REF (ns)", "SCORE (%)" ]; -var widths = [ 22, 10, 9, 9, 9 ]; -var precs = [ 0, 0, 2, 2, 2 ]; -var total = [ 0, 0, 0, 0, 0 ]; -var total_score = 0; -var total_scale = 0; - -if (typeof console == "undefined") { - var console = { log: print }; -} - -function log_line() { - var i, n, s, a; - s = ""; - for (i = 0, n = arguments.length; i < n; i++) { - if (i > 0) - s += " "; - a = arguments[i]; - if (typeof a == "number") { - total[i] += a; - a = toPrec(a, precs[i]); - s += pad_left(a, widths[i]); - } else { - s += pad_left(a, widths[i]); - } - } - console.log(s); -} - -var clocks_per_sec = 1000000; -var max_iterations = 100; -var clock_threshold = 2000; /* favoring short measuring spans */ -var min_n_argument = 1; -var get_clock; - -if (typeof globalThis.__date_clock != "function") { - console.log("using fallback millisecond clock"); - clocks_per_sec = 1000; - max_iterations = 10; - clock_threshold = 100; - get_clock = Date.now; -} else { - get_clock = globalThis.__date_clock; -} - -function log_one(text, n, ti) { - var ref; - - if (ref_data) - ref = ref_data[text]; - else - ref = null; - - ti = Math.round(ti * 100) / 100; - log_data[text] = ti; - if (typeof ref === "number") { - log_line(text, n, ti, ref, ti * 100 / ref); - total_score += ti * 100 / ref; - total_scale += 100; - } else { - log_line(text, n, ti); - total_score += 100; - total_scale += 100; - } -} - -function bench(f, text) -{ - var i, j, n, t, t1, ti, nb_its, ref, ti_n, ti_n1, min_ti; - - nb_its = n = 1; - if (f.bench) { - ti_n = f(text); - } else { - ti_n = 1000000000; - min_ti = clock_threshold / 10; - for(i = 0; i < 30; i++) { - ti = 1000000000; - for (j = 0; j < max_iterations; j++) { - t = get_clock(); - while ((t1 = get_clock()) == t) - continue; - nb_its = f(n); - if (nb_its < 0) - return; // test failure - t1 = get_clock() - t1; - if (ti > t1) - ti = t1; - } - if (ti >= min_ti) { - ti_n1 = ti / nb_its; - if (ti_n > ti_n1) - ti_n = ti_n1; - } - if (ti >= clock_threshold && n >= min_n_argument) - break; - - n = n * [ 2, 2.5, 2 ][i % 3]; - } - // to use only the best timing from the last loop, uncomment below - //ti_n = ti / nb_its; - } - /* nano seconds per iteration */ - log_one(text, n, ti_n * 1e9 / clocks_per_sec); -} - -var global_res; /* to be sure the code is not optimized */ - -function empty_loop(n) { - var j; - for(j = 0; j < n; j++) { - } - return n; -} - -function date_now(n) { - var j; - for(j = 0; j < n; j++) { - Date.now(); - } - return n; -} - -function prop_read(n) -{ - var obj, sum, j; - obj = {a: 1, b: 2, c:3, d:4 }; - sum = 0; - for(j = 0; j < n; j++) { - sum += obj.a; - sum += obj.b; - sum += obj.c; - sum += obj.d; - } - global_res = sum; - return n * 4; -} - -function prop_write(n) -{ - var obj, j; - obj = {a: 1, b: 2, c:3, d:4 }; - for(j = 0; j < n; j++) { - obj.a = j; - obj.b = j; - obj.c = j; - obj.d = j; - } - return n * 4; -} - -function prop_create(n) -{ - var obj, j; - for(j = 0; j < n; j++) { - obj = new Object(); - obj.a = 1; - obj.b = 2; - obj.c = 3; - obj.d = 4; - } - return n * 4; -} - -function prop_delete(n) -{ - var obj, j; - obj = {}; - for(j = 0; j < n; j++) { - obj[j] = 1; - } - for(j = 0; j < n; j++) { - delete obj[j]; - } - return n; -} - -function array_read(n) -{ - var tab, len, sum, i, j; - tab = []; - len = 10; - for(i = 0; i < len; i++) - tab[i] = i; - sum = 0; - for(j = 0; j < n; j++) { - sum += tab[0]; - sum += tab[1]; - sum += tab[2]; - sum += tab[3]; - sum += tab[4]; - sum += tab[5]; - sum += tab[6]; - sum += tab[7]; - sum += tab[8]; - sum += tab[9]; - } - global_res = sum; - return len * n; -} - -function array_write(n) -{ - var tab, len, i, j; - tab = []; - len = 10; - for(i = 0; i < len; i++) - tab[i] = i; - for(j = 0; j < n; j++) { - tab[0] = j; - tab[1] = j; - tab[2] = j; - tab[3] = j; - tab[4] = j; - tab[5] = j; - tab[6] = j; - tab[7] = j; - tab[8] = j; - tab[9] = j; - } - return len * n; -} - -function array_prop_create(n) -{ - var tab, i, j, len; - len = 1000; - for(j = 0; j < n; j++) { - tab = []; - for(i = 0; i < len; i++) - tab[i] = i; - } - return len * n; -} - -function array_length_decr(n) -{ - var tab, i, j, len; - len = 1000; - tab = []; - for(i = 0; i < len; i++) - tab[i] = i; - for(j = 0; j < n; j++) { - for(i = len - 1; i >= 0; i--) - tab.length = i; - } - return len * n; -} - -function array_hole_length_decr(n) -{ - var tab, i, j, len; - len = 1000; - tab = []; - for(i = 0; i < len; i++) { - if (i != 3) - tab[i] = i; - } - for(j = 0; j < n; j++) { - for(i = len - 1; i >= 0; i--) - tab.length = i; - } - return len * n; -} - -function array_push(n) -{ - var tab, i, j, len; - len = 500; - for(j = 0; j < n; j++) { - tab = []; - for(i = 0; i < len; i++) - tab.push(i); - } - return len * n; -} - -function array_pop(n) -{ - var tab, i, j, len, sum; - len = 500; - for(j = 0; j < n; j++) { - tab = []; - for(i = 0; i < len; i++) - tab[i] = i; - sum = 0; - for(i = 0; i < len; i++) - sum += tab.pop(); - global_res = sum; - } - return len * n; -} - -function typed_array_read(n) -{ - var tab, len, sum, i, j; - len = 10; - tab = new Int32Array(len); - for(i = 0; i < len; i++) - tab[i] = i; - sum = 0; - for(j = 0; j < n; j++) { - sum += tab[0]; - sum += tab[1]; - sum += tab[2]; - sum += tab[3]; - sum += tab[4]; - sum += tab[5]; - sum += tab[6]; - sum += tab[7]; - sum += tab[8]; - sum += tab[9]; - } - global_res = sum; - return len * n; -} - -function typed_array_write(n) -{ - var tab, len, i, j; - len = 10; - tab = new Int32Array(len); - for(i = 0; i < len; i++) - tab[i] = i; - for(j = 0; j < n; j++) { - tab[0] = j; - tab[1] = j; - tab[2] = j; - tab[3] = j; - tab[4] = j; - tab[5] = j; - tab[6] = j; - tab[7] = j; - tab[8] = j; - tab[9] = j; - } - return len * n; -} - -var global_var0; - -function global_read(n) -{ - var sum, j; - global_var0 = 0; - sum = 0; - for(j = 0; j < n; j++) { - sum += global_var0; - sum += global_var0; - sum += global_var0; - sum += global_var0; - } - global_res = sum; - return n * 4; -} - -var global_write = - (1, eval)(`(function global_write(n) - { - var j; - for(j = 0; j < n; j++) { - global_var0 = j; - global_var0 = j; - global_var0 = j; - global_var0 = j; - } - return n * 4; - })`); - -function global_write_strict(n) -{ - var j; - for(j = 0; j < n; j++) { - global_var0 = j; - global_var0 = j; - global_var0 = j; - global_var0 = j; - } - return n * 4; -} - -function local_destruct(n) -{ - var j, v1, v2, v3, v4; - var array = [ 1, 2, 3, 4, 5]; - var o = { a:1, b:2, c:3, d:4 }; - var a, b, c, d; - for(j = 0; j < n; j++) { - [ v1, v2,, v3, ...v4] = array; - ({ a, b, c, d } = o); - ({ a: a, b: b, c: c, d: d } = o); - } - return n * 12; -} - -var global_v1, global_v2, global_v3, global_v4; -var global_a, global_b, global_c, global_d; - -var global_destruct = - (1, eval)(`(function global_destruct(n) - { - var j, v1, v2, v3, v4; - var array = [ 1, 2, 3, 4, 5 ]; - var o = { a:1, b:2, c:3, d:4 }; - var a, b, c, d; - for(j = 0; j < n; j++) { - [ global_v1, global_v2,, global_v3, ...global_v4] = array; - ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); - } - return n * 8; - })`); - -function global_destruct_strict(n) -{ - var j, v1, v2, v3, v4; - var array = [ 1, 2, 3, 4, 5 ]; - var o = { a:1, b:2, c:3, d:4 }; - var a, b, c, d; - for(j = 0; j < n; j++) { - [ global_v1, global_v2,, global_v3, ...global_v4] = array; - ({ a: global_a, b: global_b, c: global_c, d: global_d } = o); - } - return n * 8; -} - -function func_call(n) -{ - function f(a) - { - return 1; - } - - var j, sum; - sum = 0; - for(j = 0; j < n; j++) { - sum += f(j); - sum += f(j); - sum += f(j); - sum += f(j); - } - global_res = sum; - return n * 4; -} - -function closure_var(n) -{ - function f(a) - { - sum++; - } - - var j, sum; - sum = 0; - for(j = 0; j < n; j++) { - f(j); - f(j); - f(j); - f(j); - } - global_res = sum; - return n * 4; -} - -function int_arith(n) -{ - var i, j, sum; - global_res = 0; - for(j = 0; j < n; j++) { - sum = 0; - for(i = 0; i < 1000; i++) { - sum += i * i; - } - global_res += sum; - } - return n * 1000; -} - -function float_arith(n) -{ - var i, j, sum, a, incr, a0; - global_res = 0; - a0 = 0.1; - incr = 1.1; - for(j = 0; j < n; j++) { - sum = 0; - a = a0; - for(i = 0; i < 1000; i++) { - sum += a * a; - a += incr; - } - global_res += sum; - } - return n * 1000; -} - -function bigfloat_arith(n) -{ - var i, j, sum, a, incr, a0; - global_res = 0; - a0 = BigFloat("0.1"); - incr = BigFloat("1.1"); - for(j = 0; j < n; j++) { - sum = 0; - a = a0; - for(i = 0; i < 1000; i++) { - sum += a * a; - a += incr; - } - global_res += sum; - } - return n * 1000; -} - -function float256_arith(n) -{ - return BigFloatEnv.setPrec(bigfloat_arith.bind(null, n), 237, 19); -} - -function bigint_arith(n, bits) -{ - var i, j, sum, a, incr, a0, sum0; - sum0 = global_res = BigInt(0); - a0 = BigInt(1) << BigInt(Math.floor((bits - 10) * 0.5)); - incr = BigInt(1); - for(j = 0; j < n; j++) { - sum = sum0; - a = a0; - for(i = 0; i < 1000; i++) { - sum += a * a; - a += incr; - } - global_res += sum; - } - return n * 1000; -} - -function bigint64_arith(n) -{ - return bigint_arith(n, 64); -} - -function bigint256_arith(n) -{ - return bigint_arith(n, 256); -} - -function set_collection_add(n) -{ - var s, i, j, len = 100; - s = new Set(); - for(j = 0; j < n; j++) { - for(i = 0; i < len; i++) { - s.add(String(i), i); - } - for(i = 0; i < len; i++) { - if (!s.has(String(i))) - throw Error("bug in Set"); - } - } - return n * len; -} - -function array_for(n) -{ - var r, i, j, sum; - r = []; - for(i = 0; i < 100; i++) - r[i] = i; - for(j = 0; j < n; j++) { - sum = 0; - for(i = 0; i < 100; i++) { - sum += r[i]; - } - global_res = sum; - } - return n * 100; -} - -function array_for_in(n) -{ - var r, i, j, sum; - r = []; - for(i = 0; i < 100; i++) - r[i] = i; - for(j = 0; j < n; j++) { - sum = 0; - for(i in r) { - sum += r[i]; - } - global_res = sum; - } - return n * 100; -} - -function array_for_of(n) -{ - var r, i, j, sum; - r = []; - for(i = 0; i < 100; i++) - r[i] = i; - for(j = 0; j < n; j++) { - sum = 0; - for(i of r) { - sum += i; - } - global_res = sum; - } - return n * 100; -} - -function math_min(n) -{ - var i, j, r; - r = 0; - for(j = 0; j < n; j++) { - for(i = 0; i < 1000; i++) - r = Math.min(i, 500); - global_res = r; - } - return n * 1000; -} - -/* incremental string contruction as local var */ -function string_build1(n) -{ - var i, j, r; - r = ""; - for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) - r += "x"; - global_res = r; - } - return n * 100; -} - -/* incremental string contruction as arg */ -function string_build2(n, r) -{ - var i, j; - r = ""; - for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) - r += "x"; - global_res = r; - } - return n * 100; -} - -/* incremental string contruction by prepending */ -function string_build3(n, r) -{ - var i, j; - r = ""; - for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) - r = "x" + r; - global_res = r; - } - return n * 100; -} - -/* incremental string contruction with multiple reference */ -function string_build4(n) -{ - var i, j, r, s; - r = ""; - for(j = 0; j < n; j++) { - for(i = 0; i < 100; i++) { - s = r; - r += "x"; - } - global_res = r; - } - return n * 100; -} - -/* sort bench */ - -function sort_bench(text) { - function random(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[(Math.random() * n) >> 0]; - } - function random8(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[(Math.random() * 256) >> 0]; - } - function random1(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[(Math.random() * 2) >> 0]; - } - function hill(arr, n, def) { - var mid = n >> 1; - for (var i = 0; i < mid; i++) - arr[i] = def[i]; - for (var i = mid; i < n; i++) - arr[i] = def[n - i]; - } - function comb(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[(i & 1) * i]; - } - function crisscross(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[(i & 1) ? n - i : i]; - } - function zero(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[0]; - } - function increasing(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[i]; - } - function decreasing(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[n - 1 - i]; - } - function alternate(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[i ^ 1]; - } - function jigsaw(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[i % (n >> 4)]; - } - function incbutone(arr, n, def) { - for (var i = 0; i < n; i++) - arr[i] = def[i]; - if (n > 0) - arr[n >> 2] = def[n]; - } - function incbutfirst(arr, n, def) { - if (n > 0) - arr[0] = def[n]; - for (var i = 1; i < n; i++) - arr[i] = def[i]; - } - function incbutlast(arr, n, def) { - for (var i = 0; i < n - 1; i++) - arr[i] = def[i + 1]; - if (n > 0) - arr[n - 1] = def[0]; - } - - var sort_cases = [ random, random8, random1, jigsaw, hill, comb, - crisscross, zero, increasing, decreasing, alternate, - incbutone, incbutlast, incbutfirst ]; - - var n = sort_bench.array_size || 10000; - var array_type = sort_bench.array_type || Array; - var def, arr; - var i, j, x, y; - var total = 0; - - var save_total_score = total_score; - var save_total_scale = total_scale; - - // initialize default sorted array (n + 1 elements) - def = new array_type(n + 1); - if (array_type == Array) { - for (i = 0; i <= n; i++) { - def[i] = i + ""; - } - } else { - for (i = 0; i <= n; i++) { - def[i] = i; - } - } - def.sort(); - for (var f of sort_cases) { - var ti = 0, tx = 0; - for (j = 0; j < 100; j++) { - arr = new array_type(n); - f(arr, n, def); - var t1 = get_clock(); - arr.sort(); - t1 = get_clock() - t1; - tx += t1; - if (!ti || ti > t1) - ti = t1; - if (tx >= clocks_per_sec) - break; - } - total += ti; - - i = 0; - x = arr[0]; - if (x !== void 0) { - for (i = 1; i < n; i++) { - y = arr[i]; - if (y === void 0) - break; - if (x > y) - break; - x = y; - } - } - while (i < n && arr[i] === void 0) - i++; - if (i < n) { - console.log("sort_bench: out of order error for " + f.name + - " at offset " + (i - 1) + - ": " + arr[i - 1] + " > " + arr[i]); - } - if (sort_bench.verbose) - log_one("sort_" + f.name, n, ti, n * 100); - } - total_score = save_total_score; - total_scale = save_total_scale; - return total / n / 1000; -} -sort_bench.bench = true; -sort_bench.verbose = false; - -function int_to_string(n) -{ - var s, r, j; - r = 0; - for(j = 0; j < n; j++) { - s = (j + 1).toString(); - } - return n; -} - -function float_to_string(n) -{ - var s, r, j; - r = 0; - for(j = 0; j < n; j++) { - s = (j + 0.1).toString(); - } - return n; -} - -function string_to_int(n) -{ - var s, r, j; - r = 0; - s = "12345"; - r = 0; - for(j = 0; j < n; j++) { - r += (s | 0); - } - global_res = r; - return n; -} - -function string_to_float(n) -{ - var s, r, j; - r = 0; - s = "12345.6"; - r = 0; - for(j = 0; j < n; j++) { - r -= s; - } - global_res = r; - return n; -} - -function load_result(filename) -{ - var f, str, res; - if (typeof std === "undefined") - return null; - f = std.open(filename, "r"); - if (!f) - return null; - str = f.readAsString(); - res = JSON.parse(str); - f.close(); - return res; -} - -function save_result(filename, obj) -{ - var f; - if (typeof std === "undefined") - return; - f = std.open(filename, "w"); - f.puts(JSON.stringify(obj, null, 2)); - f.puts("\n"); - f.close(); -} - -function main(argc, argv, g) -{ - var test_list = [ - empty_loop, - date_now, - prop_read, - prop_write, - prop_create, - prop_delete, - array_read, - array_write, - array_prop_create, - array_length_decr, - array_hole_length_decr, - array_push, - array_pop, - typed_array_read, - typed_array_write, - global_read, - global_write, - global_write_strict, - local_destruct, - global_destruct, - global_destruct_strict, - func_call, - closure_var, - int_arith, - float_arith, - set_collection_add, - array_for, - array_for_in, - array_for_of, - math_min, - string_build1, - string_build2, - //string_build3, - //string_build4, - sort_bench, - int_to_string, - float_to_string, - string_to_int, - string_to_float, - ]; - var tests = []; - var i, j, n, f, name; - - if (typeof BigInt == "function") { - /* BigInt test */ - test_list.push(bigint64_arith); - test_list.push(bigint256_arith); - } - if (typeof BigFloat == "function") { - /* BigFloat test */ - test_list.push(float256_arith); - } - - for (i = 1; i < argc;) { - name = argv[i++]; - if (name == "-a") { - sort_bench.verbose = true; - continue; - } - if (name == "-t") { - name = argv[i++]; - sort_bench.array_type = g[name]; - if (typeof sort_bench.array_type != "function") { - console.log("unknown array type: " + name); - return 1; - } - continue; - } - if (name == "-n") { - sort_bench.array_size = +argv[i++]; - continue; - } - for (j = 0; j < test_list.length; j++) { - f = test_list[j]; - if (name === f.name) { - tests.push(f); - break; - } - } - if (j == test_list.length) { - console.log("unknown benchmark: " + name); - return 1; - } - } - if (tests.length == 0) - tests = test_list; - - ref_data = load_result("microbench.txt"); - log_data = {}; - log_line.apply(null, heads); - n = 0; - - for(i = 0; i < tests.length; i++) { - f = tests[i]; - bench(f, f.name, ref_data, log_data); - if (ref_data && ref_data[f.name]) - n++; - } - if (ref_data) - log_line("total", "", total[2], total[3], total_score * 100 / total_scale); - else - log_line("total", "", total[2]); - - if (tests == test_list) - save_result("microbench-new.txt", log_data); -} - -if (!scriptArgs) - scriptArgs = []; -main(scriptArgs.length, scriptArgs, this); diff --git a/quickjs/tests/test262.patch b/quickjs/tests/test262.patch deleted file mode 100644 index 6576bdc..0000000 --- a/quickjs/tests/test262.patch +++ /dev/null @@ -1,71 +0,0 @@ -diff --git a/harness/atomicsHelper.js b/harness/atomicsHelper.js -index 9c1217351e..3c24755558 100644 ---- a/harness/atomicsHelper.js -+++ b/harness/atomicsHelper.js -@@ -227,10 +227,14 @@ $262.agent.waitUntil = function(typedArray, index, expected) { - * } - */ - $262.agent.timeouts = { -- yield: 100, -- small: 200, -- long: 1000, -- huge: 10000, -+// yield: 100, -+// small: 200, -+// long: 1000, -+// huge: 10000, -+ yield: 20, -+ small: 20, -+ long: 100, -+ huge: 1000, - }; - - /** -diff --git a/harness/regExpUtils.js b/harness/regExpUtils.js -index be7039fda0..7b38abf8df 100644 ---- a/harness/regExpUtils.js -+++ b/harness/regExpUtils.js -@@ -6,24 +6,27 @@ description: | - defines: [buildString, testPropertyEscapes, matchValidator] - ---*/ - -+if ($262 && typeof $262.codePointRange === "function") { -+ /* use C function to build the codePointRange (much faster with -+ slow JS engines) */ -+ codePointRange = $262.codePointRange; -+} else { -+ codePointRange = function codePointRange(start, end) { -+ const codePoints = []; -+ let length = 0; -+ for (codePoint = start; codePoint < end; codePoint++) { -+ codePoints[length++] = codePoint; -+ } -+ return String.fromCodePoint.apply(null, codePoints); -+ } -+} -+ - function buildString({ loneCodePoints, ranges }) { -- const CHUNK_SIZE = 10000; -- let result = Reflect.apply(String.fromCodePoint, null, loneCodePoints); -- for (let i = 0; i < ranges.length; i++) { -- const range = ranges[i]; -- const start = range[0]; -- const end = range[1]; -- const codePoints = []; -- for (let length = 0, codePoint = start; codePoint <= end; codePoint++) { -- codePoints[length++] = codePoint; -- if (length === CHUNK_SIZE) { -- result += Reflect.apply(String.fromCodePoint, null, codePoints); -- codePoints.length = length = 0; -- } -+ let result = String.fromCodePoint.apply(null, loneCodePoints); -+ for (const [start, end] of ranges) { -+ result += codePointRange(start, end + 1); - } -- result += Reflect.apply(String.fromCodePoint, null, codePoints); -- } -- return result; -+ return result; - } - - function testPropertyEscapes(regex, string, expression) { diff --git a/quickjs/tests/test_bignum.js b/quickjs/tests/test_bignum.js deleted file mode 100644 index f4f72a0..0000000 --- a/quickjs/tests/test_bignum.js +++ /dev/null @@ -1,326 +0,0 @@ -"use strict"; - -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -function assertThrows(err, func) -{ - var ex; - ex = false; - try { - func(); - } catch(e) { - ex = true; - assert(e instanceof err); - } - assert(ex, true, "exception expected"); -} - -// load more elaborate version of assert if available -try { __loadScript("test_assert.js"); } catch(e) {} - -/*----------------*/ - -function bigint_pow(a, n) -{ - var r, i; - r = 1n; - for(i = 0n; i < n; i++) - r *= a; - return r; -} - -/* a must be < b */ -function test_less(a, b) -{ - assert(a < b); - assert(!(b < a)); - assert(a <= b); - assert(!(b <= a)); - assert(b > a); - assert(!(a > b)); - assert(b >= a); - assert(!(a >= b)); - assert(a != b); - assert(!(a == b)); -} - -/* a must be numerically equal to b */ -function test_eq(a, b) -{ - assert(a == b); - assert(b == a); - assert(!(a != b)); - assert(!(b != a)); - assert(a <= b); - assert(b <= a); - assert(!(a < b)); - assert(a >= b); - assert(b >= a); - assert(!(a > b)); -} - -function test_bigint1() -{ - var a, r; - - test_less(2n, 3n); - test_eq(3n, 3n); - - test_less(2, 3n); - test_eq(3, 3n); - - test_less(2.1, 3n); - test_eq(Math.sqrt(4), 2n); - - a = bigint_pow(3n, 100n); - assert((a - 1n) != a); - assert(a == 515377520732011331036461129765621272702107522001n); - assert(a == 0x5a4653ca673768565b41f775d6947d55cf3813d1n); - - r = 1n << 31n; - assert(r, 2147483648n, "1 << 31n === 2147483648n"); - - r = 1n << 32n; - assert(r, 4294967296n, "1 << 32n === 4294967296n"); -} - -function test_bigint2() -{ - assert(BigInt(""), 0n); - assert(BigInt(" 123"), 123n); - assert(BigInt(" 123 "), 123n); - assertThrows(SyntaxError, () => { BigInt("+") } ); - assertThrows(SyntaxError, () => { BigInt("-") } ); - assertThrows(SyntaxError, () => { BigInt("\x00a") } ); - assertThrows(SyntaxError, () => { BigInt(" 123 r") } ); -} - -function test_divrem(div1, a, b, q) -{ - var div, divrem, t; - div = BigInt[div1]; - divrem = BigInt[div1 + "rem"]; - assert(div(a, b) == q); - t = divrem(a, b); - assert(t[0] == q); - assert(a == b * q + t[1]); -} - -function test_idiv1(div, a, b, r) -{ - test_divrem(div, a, b, r[0]); - test_divrem(div, -a, b, r[1]); - test_divrem(div, a, -b, r[2]); - test_divrem(div, -a, -b, r[3]); -} - -/* QuickJS BigInt extensions */ -function test_bigint_ext() -{ - var r; - assert(BigInt.floorLog2(0n) === -1n); - assert(BigInt.floorLog2(7n) === 2n); - - assert(BigInt.sqrt(0xffffffc000000000000000n) === 17592185913343n); - r = BigInt.sqrtrem(0xffffffc000000000000000n); - assert(r[0] === 17592185913343n); - assert(r[1] === 35167191957503n); - - test_idiv1("tdiv", 3n, 2n, [1n, -1n, -1n, 1n]); - test_idiv1("fdiv", 3n, 2n, [1n, -2n, -2n, 1n]); - test_idiv1("cdiv", 3n, 2n, [2n, -1n, -1n, 2n]); - test_idiv1("ediv", 3n, 2n, [1n, -2n, -1n, 2n]); -} - -function test_bigfloat() -{ - var e, a, b, sqrt2; - - assert(typeof 1n === "bigint"); - assert(typeof 1l === "bigfloat"); - assert(1 == 1.0l); - assert(1 !== 1.0l); - - test_less(2l, 3l); - test_eq(3l, 3l); - - test_less(2, 3l); - test_eq(3, 3l); - - test_less(2.1, 3l); - test_eq(Math.sqrt(9), 3l); - - test_less(2n, 3l); - test_eq(3n, 3l); - - e = new BigFloatEnv(128); - assert(e.prec == 128); - a = BigFloat.sqrt(2l, e); - assert(a === BigFloat.parseFloat("0x1.6a09e667f3bcc908b2fb1366ea957d3e", 0, e)); - assert(e.inexact === true); - assert(BigFloat.fpRound(a) == 0x1.6a09e667f3bcc908b2fb1366ea95l); - - b = BigFloatEnv.setPrec(BigFloat.sqrt.bind(null, 2), 128); - assert(a === b); - - assert(BigFloat.isNaN(BigFloat(NaN))); - assert(BigFloat.isFinite(1l)); - assert(!BigFloat.isFinite(1l/0l)); - - assert(BigFloat.abs(-3l) === 3l); - assert(BigFloat.sign(-3l) === -1l); - - assert(BigFloat.exp(0.2l) === 1.2214027581601698339210719946396742l); - assert(BigFloat.log(3l) === 1.0986122886681096913952452369225256l); - assert(BigFloat.pow(2.1l, 1.6l) === 3.277561666451861947162828744873745l); - - assert(BigFloat.sin(-1l) === -0.841470984807896506652502321630299l); - assert(BigFloat.cos(1l) === 0.5403023058681397174009366074429766l); - assert(BigFloat.tan(0.1l) === 0.10033467208545054505808004578111154l); - - assert(BigFloat.asin(0.3l) === 0.30469265401539750797200296122752915l); - assert(BigFloat.acos(0.4l) === 1.1592794807274085998465837940224159l); - assert(BigFloat.atan(0.7l) === 0.610725964389208616543758876490236l); - assert(BigFloat.atan2(7.1l, -5.1l) === 2.1937053809751415549388104628759813l); - - assert(BigFloat.floor(2.5l) === 2l); - assert(BigFloat.ceil(2.5l) === 3l); - assert(BigFloat.trunc(-2.5l) === -2l); - assert(BigFloat.round(2.5l) === 3l); - - assert(BigFloat.fmod(3l,2l) === 1l); - assert(BigFloat.remainder(3l,2l) === -1l); - - /* string conversion */ - assert((1234.125l).toString(), "1234.125"); - assert((1234.125l).toFixed(2), "1234.13"); - assert((1234.125l).toFixed(2, "down"), "1234.12"); - assert((1234.125l).toExponential(), "1.234125e+3"); - assert((1234.125l).toExponential(5), "1.23413e+3"); - assert((1234.125l).toExponential(5, BigFloatEnv.RNDZ), "1.23412e+3"); - assert((1234.125l).toPrecision(6), "1234.13"); - assert((1234.125l).toPrecision(6, BigFloatEnv.RNDZ), "1234.12"); - - /* string conversion with binary base */ - assert((0x123.438l).toString(16), "123.438"); - assert((0x323.438l).toString(16), "323.438"); - assert((0x723.438l).toString(16), "723.438"); - assert((0xf23.438l).toString(16), "f23.438"); - assert((0x123.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "123.44"); - assert((0x323.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "323.44"); - assert((0x723.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "723.44"); - assert((0xf23.438l).toFixed(2, BigFloatEnv.RNDNA, 16), "f23.44"); - assert((0x0.0000438l).toFixed(6, BigFloatEnv.RNDNA, 16), "0.000044"); - assert((0x1230000000l).toFixed(1, BigFloatEnv.RNDNA, 16), "1230000000.0"); - assert((0x123.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "123.44"); - assert((0x123.438l).toPrecision(5, BigFloatEnv.RNDZ, 16), "123.43"); - assert((0x323.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "323.44"); - assert((0x723.438l).toPrecision(5, BigFloatEnv.RNDNA, 16), "723.44"); - assert((-0xf23.438l).toPrecision(5, BigFloatEnv.RNDD, 16), "-f23.44"); - assert((0x123.438l).toExponential(4, BigFloatEnv.RNDNA, 16), "1.2344p+8"); -} - -function test_bigdecimal() -{ - assert(1m === 1m); - assert(1m !== 2m); - test_less(1m, 2m); - test_eq(2m, 2m); - - test_less(1, 2m); - test_eq(2, 2m); - - test_less(1.1, 2m); - test_eq(Math.sqrt(4), 2m); - - test_less(2n, 3m); - test_eq(3n, 3m); - - assert(BigDecimal("1234.1") === 1234.1m); - assert(BigDecimal(" 1234.1") === 1234.1m); - assert(BigDecimal(" 1234.1 ") === 1234.1m); - - assert(BigDecimal(0.1) === 0.1m); - assert(BigDecimal(123) === 123m); - assert(BigDecimal(true) === 1m); - - assert(123m + 1m === 124m); - assert(123m - 1m === 122m); - - assert(3.2m * 3m === 9.6m); - assert(10m / 2m === 5m); - assertThrows(RangeError, () => { 10m / 3m } ); - - assert(10m % 3m === 1m); - assert(-10m % 3m === -1m); - - assert(1234.5m ** 3m === 1881365963.625m); - assertThrows(RangeError, () => { 2m ** 3.1m } ); - assertThrows(RangeError, () => { 2m ** -3m } ); - - assert(BigDecimal.sqrt(2m, - { roundingMode: "half-even", - maximumSignificantDigits: 4 }) === 1.414m); - assert(BigDecimal.sqrt(101m, - { roundingMode: "half-even", - maximumFractionDigits: 3 }) === 10.050m); - assert(BigDecimal.sqrt(0.002m, - { roundingMode: "half-even", - maximumFractionDigits: 3 }) === 0.045m); - - assert(BigDecimal.round(3.14159m, - { roundingMode: "half-even", - maximumFractionDigits: 3 }) === 3.142m); - - assert(BigDecimal.add(3.14159m, 0.31212m, - { roundingMode: "half-even", - maximumFractionDigits: 2 }) === 3.45m); - assert(BigDecimal.sub(3.14159m, 0.31212m, - { roundingMode: "down", - maximumFractionDigits: 2 }) === 2.82m); - assert(BigDecimal.mul(3.14159m, 0.31212m, - { roundingMode: "half-even", - maximumFractionDigits: 3 }) === 0.981m); - assert(BigDecimal.mod(3.14159m, 0.31211m, - { roundingMode: "half-even", - maximumFractionDigits: 4 }) === 0.0205m); - assert(BigDecimal.div(20m, 3m, - { roundingMode: "half-even", - maximumSignificantDigits: 3 }) === 6.67m); - assert(BigDecimal.div(20m, 3m, - { roundingMode: "half-even", - maximumFractionDigits: 50 }) === - 6.66666666666666666666666666666666666666666666666667m); - - /* string conversion */ - assert((1234.125m).toString(), "1234.125"); - assert((1234.125m).toFixed(2), "1234.13"); - assert((1234.125m).toFixed(2, "down"), "1234.12"); - assert((1234.125m).toExponential(), "1.234125e+3"); - assert((1234.125m).toExponential(5), "1.23413e+3"); - assert((1234.125m).toExponential(5, "down"), "1.23412e+3"); - assert((1234.125m).toPrecision(6), "1234.13"); - assert((1234.125m).toPrecision(6, "down"), "1234.12"); - assert((-1234.125m).toPrecision(6, "floor"), "-1234.13"); -} - -test_bigint1(); -test_bigint2(); -test_bigint_ext(); -test_bigfloat(); -test_bigdecimal(); diff --git a/quickjs/tests/test_bjson.js b/quickjs/tests/test_bjson.js deleted file mode 100644 index fcbb8e6..0000000 --- a/quickjs/tests/test_bjson.js +++ /dev/null @@ -1,191 +0,0 @@ -import * as bjson from "./bjson.so"; - -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -function toHex(a) -{ - var i, s = "", tab, v; - tab = new Uint8Array(a); - for(i = 0; i < tab.length; i++) { - v = tab[i].toString(16); - if (v.length < 2) - v = "0" + v; - if (i !== 0) - s += " "; - s += v; - } - return s; -} - -function isArrayLike(a) -{ - return Array.isArray(a) || - (a instanceof Uint8ClampedArray) || - (a instanceof Uint8Array) || - (a instanceof Uint16Array) || - (a instanceof Uint32Array) || - (a instanceof Int8Array) || - (a instanceof Int16Array) || - (a instanceof Int32Array) || - (a instanceof Float32Array) || - (a instanceof Float64Array); -} - -function toStr(a) -{ - var s, i, props, prop; - - switch(typeof(a)) { - case "object": - if (a === null) - return "null"; - if (a instanceof Date) { - s = "Date(" + toStr(a.valueOf()) + ")"; - } else if (a instanceof Number) { - s = "Number(" + toStr(a.valueOf()) + ")"; - } else if (a instanceof String) { - s = "String(" + toStr(a.valueOf()) + ")"; - } else if (a instanceof Boolean) { - s = "Boolean(" + toStr(a.valueOf()) + ")"; - } else if (isArrayLike(a)) { - s = "["; - for(i = 0; i < a.length; i++) { - if (i != 0) - s += ","; - s += toStr(a[i]); - } - s += "]"; - } else { - props = Object.keys(a); - s = "{"; - for(i = 0; i < props.length; i++) { - if (i != 0) - s += ","; - prop = props[i]; - s += prop + ":" + toStr(a[prop]); - } - s += "}"; - } - return s; - case "undefined": - return "undefined"; - case "string": - return a.__quote(); - case "number": - case "bigfloat": - if (a == 0 && 1 / a < 0) - return "-0"; - else - return a.toString(); - break; - default: - return a.toString(); - } -} - -function bjson_test(a) -{ - var buf, r, a_str, r_str; - a_str = toStr(a); - buf = bjson.write(a); - if (0) { - print(a_str, "->", toHex(buf)); - } - r = bjson.read(buf, 0, buf.byteLength); - r_str = toStr(r); - if (a_str != r_str) { - print(a_str); - print(r_str); - assert(false); - } -} - -/* test multiple references to an object including circular - references */ -function bjson_test_reference() -{ - var array, buf, i, n, array_buffer; - n = 16; - array = []; - for(i = 0; i < n; i++) - array[i] = {}; - array_buffer = new ArrayBuffer(n); - for(i = 0; i < n; i++) { - array[i].next = array[(i + 1) % n]; - array[i].idx = i; - array[i].typed_array = new Uint8Array(array_buffer, i, 1); - } - buf = bjson.write(array, true); - - array = bjson.read(buf, 0, buf.byteLength, true); - - /* check the result */ - for(i = 0; i < n; i++) { - assert(array[i].next, array[(i + 1) % n]); - assert(array[i].idx, i); - assert(array[i].typed_array.buffer, array_buffer); - assert(array[i].typed_array.length, 1); - assert(array[i].typed_array.byteOffset, i); - } -} - -function bjson_test_all() -{ - var obj; - - bjson_test({x:1, y:2, if:3}); - bjson_test([1, 2, 3]); - bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]); - if (typeof BigInt !== "undefined") { - bjson_test([BigInt("1"), -BigInt("0x123456789"), - BigInt("0x123456789abcdef123456789abcdef")]); - } - if (typeof BigFloat !== "undefined") { - BigFloatEnv.setPrec(function () { - bjson_test([BigFloat("0.1"), BigFloat("-1e30"), BigFloat("0"), - BigFloat("-0"), BigFloat("Infinity"), BigFloat("-Infinity"), - 0.0 / BigFloat("0"), BigFloat.MAX_VALUE, - BigFloat.MIN_VALUE]); - }, 113, 15); - } - if (typeof BigDecimal !== "undefined") { - bjson_test([BigDecimal("0"), - BigDecimal("0.8"), BigDecimal("123321312321321e100"), - BigDecimal("-1233213123213214332333223332e100"), - BigDecimal("1.233e-1000")]); - } - - bjson_test([new Date(1234), new String("abc"), new Number(-12.1), new Boolean(true)]); - - bjson_test(new Int32Array([123123, 222111, -32222])); - bjson_test(new Float64Array([123123, 222111.5])); - - /* tested with a circular reference */ - obj = {}; - obj.x = obj; - try { - bjson.write(obj); - assert(false); - } catch(e) { - assert(e instanceof TypeError); - } - - bjson_test_reference(); -} - -bjson_test_all(); diff --git a/quickjs/tests/test_builtin.js b/quickjs/tests/test_builtin.js deleted file mode 100644 index c5c0f83..0000000 --- a/quickjs/tests/test_builtin.js +++ /dev/null @@ -1,685 +0,0 @@ -"use strict"; - -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -function assert_throws(expected_error, func) -{ - var err = false; - try { - func(); - } catch(e) { - err = true; - if (!(e instanceof expected_error)) { - throw Error("unexpected exception type"); - } - } - if (!err) { - throw Error("expected exception"); - } -} - -// load more elaborate version of assert if available -try { __loadScript("test_assert.js"); } catch(e) {} - -/*----------------*/ - -function my_func(a, b) -{ - return a + b; -} - -function test_function() -{ - function f(a, b) { - var i, tab = []; - tab.push(this); - for(i = 0; i < arguments.length; i++) - tab.push(arguments[i]); - return tab; - } - function constructor1(a) { - this.x = a; - } - - var r, g; - - r = my_func.call(null, 1, 2); - assert(r, 3, "call"); - - r = my_func.apply(null, [1, 2]); - assert(r, 3, "apply"); - - r = (function () { return 1; }).apply(null, undefined); - assert(r, 1); - - assert_throws(TypeError, (function() { - Reflect.apply((function () { return 1; }), null, undefined); - })); - - r = new Function("a", "b", "return a + b;"); - assert(r(2,3), 5, "function"); - - g = f.bind(1, 2); - assert(g.length, 1); - assert(g.name, "bound f"); - assert(g(3), [1,2,3]); - - g = constructor1.bind(null, 1); - r = new g(); - assert(r.x, 1); -} - -function test() -{ - var r, a, b, c, err; - - r = Error("hello"); - assert(r.message, "hello", "Error"); - - a = new Object(); - a.x = 1; - assert(a.x, 1, "Object"); - - assert(Object.getPrototypeOf(a), Object.prototype, "getPrototypeOf"); - Object.defineProperty(a, "y", { value: 3, writable: true, configurable: true, enumerable: true }); - assert(a.y, 3, "defineProperty"); - - Object.defineProperty(a, "z", { get: function () { return 4; }, set: function(val) { this.z_val = val; }, configurable: true, enumerable: true }); - assert(a.z, 4, "get"); - a.z = 5; - assert(a.z_val, 5, "set"); - - a = { get z() { return 4; }, set z(val) { this.z_val = val; } }; - assert(a.z, 4, "get"); - a.z = 5; - assert(a.z_val, 5, "set"); - - b = Object.create(a); - assert(Object.getPrototypeOf(b), a, "create"); - c = {u:2}; - /* XXX: refcount bug in 'b' instead of 'a' */ - Object.setPrototypeOf(a, c); - assert(Object.getPrototypeOf(a), c, "setPrototypeOf"); - - a = {}; - assert(a.toString(), "[object Object]", "toString"); - - a = {x:1}; - assert(Object.isExtensible(a), true, "extensible"); - Object.preventExtensions(a); - - err = false; - try { - a.y = 2; - } catch(e) { - err = true; - } - assert(Object.isExtensible(a), false, "extensible"); - assert(typeof a.y, "undefined", "extensible"); - assert(err, true, "extensible"); -} - -function test_enum() -{ - var a, tab; - a = {x:1, - "18014398509481984": 1, - "9007199254740992": 1, - "9007199254740991": 1, - "4294967296": 1, - "4294967295": 1, - y:1, - "4294967294": 1, - "1": 2}; - tab = Object.keys(a); -// console.log("tab=" + tab.toString()); - assert(tab, ["1","4294967294","x","18014398509481984","9007199254740992","9007199254740991","4294967296","4294967295","y"], "keys"); -} - -function test_array() -{ - var a, err; - - a = [1, 2, 3]; - assert(a.length, 3, "array"); - assert(a[2], 3, "array1"); - - a = new Array(10); - assert(a.length, 10, "array2"); - - a = new Array(1, 2); - assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array3"); - - a = [1, 2, 3]; - a.length = 2; - assert(a.length === 2 && a[0] === 1 && a[1] === 2, true, "array4"); - - a = []; - a[1] = 10; - a[4] = 3; - assert(a.length, 5); - - a = [1,2]; - a.length = 5; - a[4] = 1; - a.length = 4; - assert(a[4] !== 1, true, "array5"); - - a = [1,2]; - a.push(3,4); - assert(a.join(), "1,2,3,4", "join"); - - a = [1,2,3,4,5]; - Object.defineProperty(a, "3", { configurable: false }); - err = false; - try { - a.length = 2; - } catch(e) { - err = true; - } - assert(err && a.toString() === "1,2,3,4"); -} - -function test_string() -{ - var a; - a = String("abc"); - assert(a.length, 3, "string"); - assert(a[1], "b", "string"); - assert(a.charCodeAt(1), 0x62, "string"); - assert(String.fromCharCode(65), "A", "string"); - assert(String.fromCharCode.apply(null, [65, 66, 67]), "ABC", "string"); - assert(a.charAt(1), "b"); - assert(a.charAt(-1), ""); - assert(a.charAt(3), ""); - - a = "abcd"; - assert(a.substring(1, 3), "bc", "substring"); - a = String.fromCharCode(0x20ac); - assert(a.charCodeAt(0), 0x20ac, "unicode"); - assert(a, "€", "unicode"); - assert(a, "\u20ac", "unicode"); - assert(a, "\u{20ac}", "unicode"); - assert("a", "\x61", "unicode"); - - a = "\u{10ffff}"; - assert(a.length, 2, "unicode"); - assert(a, "\u{dbff}\u{dfff}", "unicode"); - assert(a.codePointAt(0), 0x10ffff); - assert(String.fromCodePoint(0x10ffff), a); - - assert("a".concat("b", "c"), "abc"); - - assert("abcabc".indexOf("cab"), 2); - assert("abcabc".indexOf("cab2"), -1); - assert("abc".indexOf("c"), 2); - - assert("aaa".indexOf("a"), 0); - assert("aaa".indexOf("a", NaN), 0); - assert("aaa".indexOf("a", -Infinity), 0); - assert("aaa".indexOf("a", -1), 0); - assert("aaa".indexOf("a", -0), 0); - assert("aaa".indexOf("a", 0), 0); - assert("aaa".indexOf("a", 1), 1); - assert("aaa".indexOf("a", 2), 2); - assert("aaa".indexOf("a", 3), -1); - assert("aaa".indexOf("a", 4), -1); - assert("aaa".indexOf("a", Infinity), -1); - - assert("aaa".indexOf(""), 0); - assert("aaa".indexOf("", NaN), 0); - assert("aaa".indexOf("", -Infinity), 0); - assert("aaa".indexOf("", -1), 0); - assert("aaa".indexOf("", -0), 0); - assert("aaa".indexOf("", 0), 0); - assert("aaa".indexOf("", 1), 1); - assert("aaa".indexOf("", 2), 2); - assert("aaa".indexOf("", 3), 3); - assert("aaa".indexOf("", 4), 3); - assert("aaa".indexOf("", Infinity), 3); - - assert("aaa".lastIndexOf("a"), 2); - assert("aaa".lastIndexOf("a", NaN), 2); - assert("aaa".lastIndexOf("a", -Infinity), 0); - assert("aaa".lastIndexOf("a", -1), 0); - assert("aaa".lastIndexOf("a", -0), 0); - assert("aaa".lastIndexOf("a", 0), 0); - assert("aaa".lastIndexOf("a", 1), 1); - assert("aaa".lastIndexOf("a", 2), 2); - assert("aaa".lastIndexOf("a", 3), 2); - assert("aaa".lastIndexOf("a", 4), 2); - assert("aaa".lastIndexOf("a", Infinity), 2); - - assert("aaa".lastIndexOf(""), 3); - assert("aaa".lastIndexOf("", NaN), 3); - assert("aaa".lastIndexOf("", -Infinity), 0); - assert("aaa".lastIndexOf("", -1), 0); - assert("aaa".lastIndexOf("", -0), 0); - assert("aaa".lastIndexOf("", 0), 0); - assert("aaa".lastIndexOf("", 1), 1); - assert("aaa".lastIndexOf("", 2), 2); - assert("aaa".lastIndexOf("", 3), 3); - assert("aaa".lastIndexOf("", 4), 3); - assert("aaa".lastIndexOf("", Infinity), 3); - - assert("a,b,c".split(","), ["a","b","c"]); - assert(",b,c".split(","), ["","b","c"]); - assert("a,b,".split(","), ["a","b",""]); - - assert("aaaa".split(), [ "aaaa" ]); - assert("aaaa".split(undefined, 0), [ ]); - assert("aaaa".split(""), [ "a", "a", "a", "a" ]); - assert("aaaa".split("", 0), [ ]); - assert("aaaa".split("", 1), [ "a" ]); - assert("aaaa".split("", 2), [ "a", "a" ]); - assert("aaaa".split("a"), [ "", "", "", "", "" ]); - assert("aaaa".split("a", 2), [ "", "" ]); - assert("aaaa".split("aa"), [ "", "", "" ]); - assert("aaaa".split("aa", 0), [ ]); - assert("aaaa".split("aa", 1), [ "" ]); - assert("aaaa".split("aa", 2), [ "", "" ]); - assert("aaaa".split("aaa"), [ "", "a" ]); - assert("aaaa".split("aaaa"), [ "", "" ]); - assert("aaaa".split("aaaaa"), [ "aaaa" ]); - assert("aaaa".split("aaaaa", 0), [ ]); - assert("aaaa".split("aaaaa", 1), [ "aaaa" ]); - - assert(eval('"\0"'), "\0"); - - assert("abc".padStart(Infinity, ""), "abc"); -} - -function test_math() -{ - var a; - a = 1.4; - assert(Math.floor(a), 1); - assert(Math.ceil(a), 2); - assert(Math.imul(0x12345678, 123), -1088058456); - assert(Math.fround(0.1), 0.10000000149011612); - assert(Math.hypot() == 0); - assert(Math.hypot(-2) == 2); - assert(Math.hypot(3, 4) == 5); - assert(Math.abs(Math.hypot(3, 4, 5) - 7.0710678118654755) <= 1e-15); -} - -function test_number() -{ - assert(parseInt("123"), 123); - assert(parseInt(" 123r"), 123); - assert(parseInt("0x123"), 0x123); - assert(parseInt("0o123"), 0); - assert(+" 123 ", 123); - assert(+"0b111", 7); - assert(+"0o123", 83); - assert(parseFloat("0x1234"), 0); - assert(parseFloat("Infinity"), Infinity); - assert(parseFloat("-Infinity"), -Infinity); - assert(parseFloat("123.2"), 123.2); - assert(parseFloat("123.2e3"), 123200); - assert(Number.isNaN(Number("+"))); - assert(Number.isNaN(Number("-"))); - assert(Number.isNaN(Number("\x00a"))); - - assert((25).toExponential(0), "3e+1"); - assert((-25).toExponential(0), "-3e+1"); - assert((2.5).toPrecision(1), "3"); - assert((-2.5).toPrecision(1), "-3"); - assert((1.125).toFixed(2), "1.13"); - assert((-1.125).toFixed(2), "-1.13"); -} - -function test_eval2() -{ - var g_call_count = 0; - /* force non strict mode for f1 and f2 */ - var f1 = new Function("eval", "eval(1, 2)"); - var f2 = new Function("eval", "eval(...[1, 2])"); - function g(a, b) { - assert(a, 1); - assert(b, 2); - g_call_count++; - } - f1(g); - f2(g); - assert(g_call_count, 2); -} - -function test_eval() -{ - function f(b) { - var x = 1; - return eval(b); - } - var r, a; - - r = eval("1+1;"); - assert(r, 2, "eval"); - - r = eval("var my_var=2; my_var;"); - assert(r, 2, "eval"); - assert(typeof my_var, "undefined"); - - assert(eval("if (1) 2; else 3;"), 2); - assert(eval("if (0) 2; else 3;"), 3); - - assert(f.call(1, "this"), 1); - - a = 2; - assert(eval("a"), 2); - - eval("a = 3"); - assert(a, 3); - - assert(f("arguments.length", 1), 2); - assert(f("arguments[1]", 1), 1); - - a = 4; - assert(f("a"), 4); - f("a=3"); - assert(a, 3); - - test_eval2(); -} - -function test_typed_array() -{ - var buffer, a, i, str; - - a = new Uint8Array(4); - assert(a.length, 4); - for(i = 0; i < a.length; i++) - a[i] = i; - assert(a.join(","), "0,1,2,3"); - a[0] = -1; - assert(a[0], 255); - - a = new Int8Array(3); - a[0] = 255; - assert(a[0], -1); - - a = new Int32Array(3); - a[0] = Math.pow(2, 32) - 1; - assert(a[0], -1); - assert(a.BYTES_PER_ELEMENT, 4); - - a = new Uint8ClampedArray(4); - a[0] = -100; - a[1] = 1.5; - a[2] = 0.5; - a[3] = 1233.5; - assert(a.toString(), "0,2,0,255"); - - buffer = new ArrayBuffer(16); - assert(buffer.byteLength, 16); - a = new Uint32Array(buffer, 12, 1); - assert(a.length, 1); - a[0] = -1; - - a = new Uint16Array(buffer, 2); - a[0] = -1; - - a = new Float32Array(buffer, 8, 1); - a[0] = 1; - - a = new Uint8Array(buffer); - - str = a.toString(); - /* test little and big endian cases */ - if (str !== "0,0,255,255,0,0,0,0,0,0,128,63,255,255,255,255" && - str !== "0,0,255,255,0,0,0,0,63,128,0,0,255,255,255,255") { - assert(false); - } - - assert(a.buffer, buffer); - - a = new Uint8Array([1, 2, 3, 4]); - assert(a.toString(), "1,2,3,4"); - a.set([10, 11], 2); - assert(a.toString(), "1,2,10,11"); -} - -function test_json() -{ - var a, s; - s = '{"x":1,"y":true,"z":null,"a":[1,2,3],"s":"str"}'; - a = JSON.parse(s); - assert(a.x, 1); - assert(a.y, true); - assert(a.z, null); - assert(JSON.stringify(a), s); - - /* indentation test */ - assert(JSON.stringify([[{x:1,y:{},z:[]},2,3]],undefined,1), -`[ - [ - { - "x": 1, - "y": {}, - "z": [] - }, - 2, - 3 - ] -]`); -} - -function test_date() -{ - var d = new Date(1506098258091), a, s; - assert(d.toISOString(), "2017-09-22T16:37:38.091Z"); - d.setUTCHours(18, 10, 11); - assert(d.toISOString(), "2017-09-22T18:10:11.091Z"); - a = Date.parse(d.toISOString()); - assert((new Date(a)).toISOString(), d.toISOString()); - s = new Date("2020-01-01T01:01:01.1Z").toISOString(); - assert(s == "2020-01-01T01:01:01.100Z"); - s = new Date("2020-01-01T01:01:01.12Z").toISOString(); - assert(s == "2020-01-01T01:01:01.120Z"); - s = new Date("2020-01-01T01:01:01.123Z").toISOString(); - assert(s == "2020-01-01T01:01:01.123Z"); - s = new Date("2020-01-01T01:01:01.1234Z").toISOString(); - assert(s == "2020-01-01T01:01:01.123Z"); - s = new Date("2020-01-01T01:01:01.12345Z").toISOString(); - assert(s == "2020-01-01T01:01:01.123Z"); - s = new Date("2020-01-01T01:01:01.1235Z").toISOString(); - assert(s == "2020-01-01T01:01:01.124Z"); - s = new Date("2020-01-01T01:01:01.9999Z").toISOString(); - assert(s == "2020-01-01T01:01:02.000Z"); -} - -function test_regexp() -{ - var a, str; - str = "abbbbbc"; - a = /(b+)c/.exec(str); - assert(a[0], "bbbbbc"); - assert(a[1], "bbbbb"); - assert(a.index, 1); - assert(a.input, str); - a = /(b+)c/.test(str); - assert(a, true); - assert(/\x61/.exec("a")[0], "a"); - assert(/\u0061/.exec("a")[0], "a"); - assert(/\ca/.exec("\x01")[0], "\x01"); - assert(/\\a/.exec("\\a")[0], "\\a"); - assert(/\c0/.exec("\\c0")[0], "\\c0"); - - a = /(\.(?=com|org)|\/)/.exec("ah.com"); - assert(a.index === 2 && a[0] === "."); - - a = /(\.(?!com|org)|\/)/.exec("ah.com"); - assert(a, null); - - a = /(?=(a+))/.exec("baaabac"); - assert(a.index === 1 && a[0] === "" && a[1] === "aaa"); - - a = /(z)((a+)?(b+)?(c))*/.exec("zaacbbbcac"); - assert(a, ["zaacbbbcac","z","ac","a",,"c"]); - - a = eval("/\0a/"); - assert(a.toString(), "/\0a/"); - assert(a.exec("\0a")[0], "\0a"); - - assert(/{1a}/.toString(), "/{1a}/"); - a = /a{1+/.exec("a{11"); - assert(a, ["a{11"] ); -} - -function test_symbol() -{ - var a, b, obj, c; - a = Symbol("abc"); - obj = {}; - obj[a] = 2; - assert(obj[a], 2); - assert(typeof obj["abc"], "undefined"); - assert(String(a), "Symbol(abc)"); - b = Symbol("abc"); - assert(a == a); - assert(a === a); - assert(a != b); - assert(a !== b); - - b = Symbol.for("abc"); - c = Symbol.for("abc"); - assert(b === c); - assert(b !== a); - - assert(Symbol.keyFor(b), "abc"); - assert(Symbol.keyFor(a), undefined); - - a = Symbol("aaa"); - assert(a.valueOf(), a); - assert(a.toString(), "Symbol(aaa)"); - - b = Object(a); - assert(b.valueOf(), a); - assert(b.toString(), "Symbol(aaa)"); -} - -function test_map() -{ - var a, i, n, tab, o, v; - n = 1000; - a = new Map(); - tab = []; - for(i = 0; i < n; i++) { - v = { }; - o = { id: i }; - tab[i] = [o, v]; - a.set(o, v); - } - - assert(a.size, n); - for(i = 0; i < n; i++) { - assert(a.get(tab[i][0]), tab[i][1]); - } - - i = 0; - a.forEach(function (v, o) { - assert(o, tab[i++][0]); - assert(a.has(o)); - assert(a.delete(o)); - assert(!a.has(o)); - }); - - assert(a.size, 0); -} - -function test_weak_map() -{ - var a, i, n, tab, o, v, n2; - a = new WeakMap(); - n = 10; - tab = []; - for(i = 0; i < n; i++) { - v = { }; - o = { id: i }; - tab[i] = [o, v]; - a.set(o, v); - } - o = null; - - n2 = n >> 1; - for(i = 0; i < n2; i++) { - a.delete(tab[i][0]); - } - for(i = n2; i < n; i++) { - tab[i][0] = null; /* should remove the object from the WeakMap too */ - } - /* the WeakMap should be empty here */ -} - -function test_generator() -{ - function *f() { - var ret; - yield 1; - ret = yield 2; - assert(ret, "next_arg"); - return 3; - } - function *f2() { - yield 1; - yield 2; - return "ret_val"; - } - function *f1() { - var ret = yield *f2(); - assert(ret, "ret_val"); - return 3; - } - var g, v; - g = f(); - v = g.next(); - assert(v.value === 1 && v.done === false); - v = g.next(); - assert(v.value === 2 && v.done === false); - v = g.next("next_arg"); - assert(v.value === 3 && v.done === true); - v = g.next(); - assert(v.value === undefined && v.done === true); - - g = f1(); - v = g.next(); - assert(v.value === 1 && v.done === false); - v = g.next(); - assert(v.value === 2 && v.done === false); - v = g.next(); - assert(v.value === 3 && v.done === true); - v = g.next(); - assert(v.value === undefined && v.done === true); -} - -test(); -test_function(); -test_enum(); -test_array(); -test_string(); -test_math(); -test_number(); -test_eval(); -test_typed_array(); -test_json(); -test_date(); -test_regexp(); -test_symbol(); -test_map(); -test_weak_map(); -test_generator(); diff --git a/quickjs/tests/test_closure.js b/quickjs/tests/test_closure.js deleted file mode 100644 index aa1d17e..0000000 --- a/quickjs/tests/test_closure.js +++ /dev/null @@ -1,221 +0,0 @@ -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -// load more elaborate version of assert if available -try { __loadScript("test_assert.js"); } catch(e) {} - -/*----------------*/ - -var log_str = ""; - -function log(str) -{ - log_str += str + ","; -} - -function f(a, b, c) -{ - var x = 10; - log("a="+a); - function g(d) { - function h() { - log("d=" + d); - log("x=" + x); - } - log("b=" + b); - log("c=" + c); - h(); - } - g(4); - return g; -} - -var g1 = f(1, 2, 3); -g1(5); - -assert(log_str, "a=1,b=2,c=3,d=4,x=10,b=2,c=3,d=5,x=10,", "closure1"); - -function test_closure1() -{ - function f2() - { - var val = 1; - - function set(a) { - val = a; - } - function get(a) { - return val; - } - return { "set": set, "get": get }; - } - - var obj = f2(); - obj.set(10); - var r; - r = obj.get(); - assert(r, 10, "closure2"); -} - -function test_closure2() -{ - var expr_func = function myfunc1(n) { - function myfunc2(n) { - return myfunc1(n - 1); - } - if (n == 0) - return 0; - else - return myfunc2(n); - }; - var r; - r = expr_func(1); - assert(r, 0, "expr_func"); -} - -function test_closure3() -{ - function fib(n) - { - if (n <= 0) - return 0; - else if (n == 1) - return 1; - else - return fib(n - 1) + fib(n - 2); - } - - var fib_func = function fib1(n) - { - if (n <= 0) - return 0; - else if (n == 1) - return 1; - else - return fib1(n - 1) + fib1(n - 2); - }; - - assert(fib(6), 8, "fib"); - assert(fib_func(6), 8, "fib_func"); -} - -function test_arrow_function() -{ - "use strict"; - - function f1() { - return (() => arguments)(); - } - function f2() { - return (() => this)(); - } - function f3() { - return (() => eval("this"))(); - } - function f4() { - return (() => eval("new.target"))(); - } - var a; - - a = f1(1, 2); - assert(a.length, 2); - assert(a[0] === 1 && a[1] === 2); - - assert(f2.call("this_val") === "this_val"); - assert(f3.call("this_val") === "this_val"); - assert(new f4() === f4); - - var o1 = { f() { return this; } }; - var o2 = { f() { - return (() => eval("super.f()"))(); - } }; - o2.__proto__ = o1; - - assert(o2.f() === o2); -} - -function test_with() -{ - var o1 = { x: "o1", y: "o1" }; - var x = "local"; - eval('var z="var_obj";'); - assert(z === "var_obj"); - with (o1) { - assert(x === "o1"); - assert(eval("x") === "o1"); - var f = function () { - o2 = { x: "o2" }; - with (o2) { - assert(x === "o2"); - assert(y === "o1"); - assert(z === "var_obj"); - assert(eval("x") === "o2"); - assert(eval("y") === "o1"); - assert(eval("z") === "var_obj"); - assert(eval('eval("x")') === "o2"); - } - }; - f(); - } -} - -function test_eval_closure() -{ - var tab; - - tab = []; - for(let i = 0; i < 3; i++) { - eval("tab.push(function g1() { return i; })"); - } - for(let i = 0; i < 3; i++) { - assert(tab[i]() === i); - } - - tab = []; - for(let i = 0; i < 3; i++) { - let f = function f() { - eval("tab.push(function g2() { return i; })"); - }; - f(); - } - for(let i = 0; i < 3; i++) { - assert(tab[i]() === i); - } -} - -function test_eval_const() -{ - const a = 1; - var success = false; - var f = function () { - eval("a = 1"); - }; - try { - f(); - } catch(e) { - success = (e instanceof TypeError); - } - assert(success); -} - -test_closure1(); -test_closure2(); -test_closure3(); -test_arrow_function(); -test_with(); -test_eval_closure(); -test_eval_const(); diff --git a/quickjs/tests/test_language.js b/quickjs/tests/test_language.js deleted file mode 100644 index 8d13deb..0000000 --- a/quickjs/tests/test_language.js +++ /dev/null @@ -1,547 +0,0 @@ -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -function assert_throws(expected_error, func) -{ - var err = false; - try { - func(); - } catch(e) { - err = true; - if (!(e instanceof expected_error)) { - throw Error("unexpected exception type"); - } - } - if (!err) { - throw Error("expected exception"); - } -} - -// load more elaborate version of assert if available -try { __loadScript("test_assert.js"); } catch(e) {} - -/*----------------*/ - -function test_op1() -{ - var r, a; - r = 1 + 2; - assert(r, 3, "1 + 2 === 3"); - - r = 1 - 2; - assert(r, -1, "1 - 2 === -1"); - - r = -1; - assert(r, -1, "-1 === -1"); - - r = +2; - assert(r, 2, "+2 === 2"); - - r = 2 * 3; - assert(r, 6, "2 * 3 === 6"); - - r = 4 / 2; - assert(r, 2, "4 / 2 === 2"); - - r = 4 % 3; - assert(r, 1, "4 % 3 === 3"); - - r = 4 << 2; - assert(r, 16, "4 << 2 === 16"); - - r = 1 << 0; - assert(r, 1, "1 << 0 === 1"); - - r = 1 << 31; - assert(r, -2147483648, "1 << 31 === -2147483648"); - - r = 1 << 32; - assert(r, 1, "1 << 32 === 1"); - - r = (1 << 31) < 0; - assert(r, true, "(1 << 31) < 0 === true"); - - r = -4 >> 1; - assert(r, -2, "-4 >> 1 === -2"); - - r = -4 >>> 1; - assert(r, 0x7ffffffe, "-4 >>> 1 === 0x7ffffffe"); - - r = 1 & 1; - assert(r, 1, "1 & 1 === 1"); - - r = 0 | 1; - assert(r, 1, "0 | 1 === 1"); - - r = 1 ^ 1; - assert(r, 0, "1 ^ 1 === 0"); - - r = ~1; - assert(r, -2, "~1 === -2"); - - r = !1; - assert(r, false, "!1 === false"); - - assert((1 < 2), true, "(1 < 2) === true"); - - assert((2 > 1), true, "(2 > 1) === true"); - - assert(('b' > 'a'), true, "('b' > 'a') === true"); - - assert(2 ** 8, 256, "2 ** 8 === 256"); -} - -function test_cvt() -{ - assert((NaN | 0) === 0); - assert((Infinity | 0) === 0); - assert(((-Infinity) | 0) === 0); - assert(("12345" | 0) === 12345); - assert(("0x12345" | 0) === 0x12345); - assert(((4294967296 * 3 - 4) | 0) === -4); - - assert(("12345" >>> 0) === 12345); - assert(("0x12345" >>> 0) === 0x12345); - assert((NaN >>> 0) === 0); - assert((Infinity >>> 0) === 0); - assert(((-Infinity) >>> 0) === 0); - assert(((4294967296 * 3 - 4) >>> 0) === (4294967296 - 4)); -} - -function test_eq() -{ - assert(null == undefined); - assert(undefined == null); - assert(true == 1); - assert(0 == false); - assert("" == 0); - assert("123" == 123); - assert("122" != 123); - assert((new Number(1)) == 1); - assert(2 == (new Number(2))); - assert((new String("abc")) == "abc"); - assert({} != "abc"); -} - -function test_inc_dec() -{ - var a, r; - - a = 1; - r = a++; - assert(r === 1 && a === 2, true, "++"); - - a = 1; - r = ++a; - assert(r === 2 && a === 2, true, "++"); - - a = 1; - r = a--; - assert(r === 1 && a === 0, true, "--"); - - a = 1; - r = --a; - assert(r === 0 && a === 0, true, "--"); - - a = {x:true}; - a.x++; - assert(a.x, 2, "++"); - - a = {x:true}; - a.x--; - assert(a.x, 0, "--"); - - a = [true]; - a[0]++; - assert(a[0], 2, "++"); - - a = {x:true}; - r = a.x++; - assert(r === 1 && a.x === 2, true, "++"); - - a = {x:true}; - r = a.x--; - assert(r === 1 && a.x === 0, true, "--"); - - a = [true]; - r = a[0]++; - assert(r === 1 && a[0] === 2, true, "++"); - - a = [true]; - r = a[0]--; - assert(r === 1 && a[0] === 0, true, "--"); -} - -function F(x) -{ - this.x = x; -} - -function test_op2() -{ - var a, b; - a = new Object; - a.x = 1; - assert(a.x, 1, "new"); - b = new F(2); - assert(b.x, 2, "new"); - - a = {x : 2}; - assert(("x" in a), true, "in"); - assert(("y" in a), false, "in"); - - a = {}; - assert((a instanceof Object), true, "instanceof"); - assert((a instanceof String), false, "instanceof"); - - assert((typeof 1), "number", "typeof"); - assert((typeof Object), "function", "typeof"); - assert((typeof null), "object", "typeof"); - assert((typeof unknown_var), "undefined", "typeof"); - - a = {x: 1, if: 2, async: 3}; - assert(a.if === 2); - assert(a.async === 3); -} - -function test_delete() -{ - var a, err; - - a = {x: 1, y: 1}; - assert((delete a.x), true, "delete"); - assert(("x" in a), false, "delete"); - - /* the following are not tested by test262 */ - assert(delete "abc"[100], true); - - err = false; - try { - delete null.a; - } catch(e) { - err = (e instanceof TypeError); - } - assert(err, true, "delete"); - - err = false; - try { - a = { f() { delete super.a; } }; - a.f(); - } catch(e) { - err = (e instanceof ReferenceError); - } - assert(err, true, "delete"); -} - -function test_prototype() -{ - var f = function f() { }; - assert(f.prototype.constructor, f, "prototype"); - - var g = function g() { }; - /* QuickJS bug */ - Object.defineProperty(g, "prototype", { writable: false }); - assert(g.prototype.constructor, g, "prototype"); -} - -function test_arguments() -{ - function f2() { - assert(arguments.length, 2, "arguments"); - assert(arguments[0], 1, "arguments"); - assert(arguments[1], 3, "arguments"); - } - f2(1, 3); -} - -function test_class() -{ - var o; - class C { - constructor() { - this.x = 10; - } - f() { - return 1; - } - static F() { - return -1; - } - get y() { - return 12; - } - }; - class D extends C { - constructor() { - super(); - this.z = 20; - } - g() { - return 2; - } - static G() { - return -2; - } - h() { - return super.f(); - } - static H() { - return super["F"](); - } - } - - assert(C.F() === -1); - assert(Object.getOwnPropertyDescriptor(C.prototype, "y").get.name === "get y"); - - o = new C(); - assert(o.f() === 1); - assert(o.x === 10); - - assert(D.F() === -1); - assert(D.G() === -2); - assert(D.H() === -1); - - o = new D(); - assert(o.f() === 1); - assert(o.g() === 2); - assert(o.x === 10); - assert(o.z === 20); - assert(o.h() === 1); - - /* test class name scope */ - var E1 = class E { static F() { return E; } }; - assert(E1 === E1.F()); -}; - -function test_template() -{ - var a, b; - b = 123; - a = `abc${b}d`; - assert(a, "abc123d"); - - a = String.raw `abc${b}d`; - assert(a, "abc123d"); - - a = "aaa"; - b = "bbb"; - assert(`aaa${a, b}ccc`, "aaabbbccc"); -} - -function test_template_skip() -{ - var a = "Bar"; - var { b = `${a + `a${a}` }baz` } = {}; - assert(b, "BaraBarbaz"); -} - -function test_object_literal() -{ - var x = 0, get = 1, set = 2; async = 3; - a = { get: 2, set: 3, async: 4 }; - assert(JSON.stringify(a), '{"get":2,"set":3,"async":4}'); - - a = { x, get, set, async }; - assert(JSON.stringify(a), '{"x":0,"get":1,"set":2,"async":3}'); -} - -function test_regexp_skip() -{ - var a, b; - [a, b = /abc\(/] = [1]; - assert(a === 1); - - [a, b =/abc\(/] = [2]; - assert(a === 2); -} - -function test_labels() -{ - do x: { break x; } while(0); - if (1) - x: { break x; } - else - x: { break x; } - with ({}) x: { break x; }; - while (0) x: { break x; }; -} - -function test_destructuring() -{ - function * g () { return 0; }; - var [x] = g(); - assert(x, void 0); -} - -function test_spread() -{ - var x; - x = [1, 2, ...[3, 4]]; - assert(x.toString(), "1,2,3,4"); - - x = [ ...[ , ] ]; - assert(Object.getOwnPropertyNames(x).toString(), "0,length"); -} - -function test_function_length() -{ - assert( ((a, b = 1, c) => {}).length, 1); - assert( (([a,b]) => {}).length, 1); - assert( (({a,b}) => {}).length, 1); - assert( ((c, [a,b] = 1, d) => {}).length, 1); -} - -function test_argument_scope() -{ - var f; - var c = "global"; - - f = function(a = eval("var arguments")) {}; - assert_throws(SyntaxError, f); - - f = function(a = eval("1"), b = arguments[0]) { return b; }; - assert(f(12), 12); - - f = function(a, b = arguments[0]) { return b; }; - assert(f(12), 12); - - f = function(a, b = () => arguments) { return b; }; - assert(f(12)()[0], 12); - - f = function(a = eval("1"), b = () => arguments) { return b; }; - assert(f(12)()[0], 12); - - (function() { - "use strict"; - f = function(a = this) { return a; }; - assert(f.call(123), 123); - - f = function f(a = f) { return a; }; - assert(f(), f); - - f = function f(a = eval("f")) { return a; }; - assert(f(), f); - })(); - - f = (a = eval("var c = 1"), probe = () => c) => { - var c = 2; - assert(c, 2); - assert(probe(), 1); - } - f(); - - f = (a = eval("var arguments = 1"), probe = () => arguments) => { - var arguments = 2; - assert(arguments, 2); - assert(probe(), 1); - } - f(); - - f = function f(a = eval("var c = 1"), b = c, probe = () => c) { - assert(b, 1); - assert(c, 1); - assert(probe(), 1) - } - f(); - - assert(c, "global"); - f = function f(a, b = c, probe = () => c) { - eval("var c = 1"); - assert(c, 1); - assert(b, "global"); - assert(probe(), "global") - } - f(); - assert(c, "global"); - - f = function f(a = eval("var c = 1"), probe = (d = eval("c")) => d) { - assert(probe(), 1) - } - f(); -} - -function test_function_expr_name() -{ - var f; - - /* non strict mode test : assignment to the function name silently - fails */ - - f = function myfunc() { - myfunc = 1; - return myfunc; - }; - assert(f(), f); - - f = function myfunc() { - myfunc = 1; - (() => { - myfunc = 1; - })(); - return myfunc; - }; - assert(f(), f); - - f = function myfunc() { - eval("myfunc = 1"); - return myfunc; - }; - assert(f(), f); - - /* strict mode test : assignment to the function name raises a - TypeError exception */ - - f = function myfunc() { - "use strict"; - myfunc = 1; - }; - assert_throws(TypeError, f); - - f = function myfunc() { - "use strict"; - (() => { - myfunc = 1; - })(); - }; - assert_throws(TypeError, f); - - f = function myfunc() { - "use strict"; - eval("myfunc = 1"); - }; - assert_throws(TypeError, f); -} - -test_op1(); -test_cvt(); -test_eq(); -test_inc_dec(); -test_op2(); -test_delete(); -test_prototype(); -test_arguments(); -test_class(); -test_template(); -test_template_skip(); -test_object_literal(); -test_regexp_skip(); -test_labels(); -test_destructuring(); -test_spread(); -test_function_length(); -test_argument_scope(); -test_function_expr_name(); diff --git a/quickjs/tests/test_loop.js b/quickjs/tests/test_loop.js deleted file mode 100644 index 5fda9d8..0000000 --- a/quickjs/tests/test_loop.js +++ /dev/null @@ -1,368 +0,0 @@ -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -// load more elaborate version of assert if available -try { __loadScript("test_assert.js"); } catch(e) {} - -/*----------------*/ - -function test_while() -{ - var i, c; - i = 0; - c = 0; - while (i < 3) { - c++; - i++; - } - assert(c === 3); -} - -function test_while_break() -{ - var i, c; - i = 0; - c = 0; - while (i < 3) { - c++; - if (i == 1) - break; - i++; - } - assert(c === 2 && i === 1); -} - -function test_do_while() -{ - var i, c; - i = 0; - c = 0; - do { - c++; - i++; - } while (i < 3); - assert(c === 3 && i === 3); -} - -function test_for() -{ - var i, c; - c = 0; - for(i = 0; i < 3; i++) { - c++; - } - assert(c === 3 && i === 3); - - c = 0; - for(var j = 0; j < 3; j++) { - c++; - } - assert(c === 3 && j === 3); -} - -function test_for_in() -{ - var i, tab, a, b; - - tab = []; - for(i in {x:1, y: 2}) { - tab.push(i); - } - assert(tab.toString(), "x,y", "for_in"); - - /* prototype chain test */ - a = {x:2, y: 2, "1": 3}; - b = {"4" : 3 }; - Object.setPrototypeOf(a, b); - tab = []; - for(i in a) { - tab.push(i); - } - assert(tab.toString(), "1,x,y,4", "for_in"); - - /* non enumerable properties hide enumerables ones in the - prototype chain */ - a = {y: 2, "1": 3}; - Object.defineProperty(a, "x", { value: 1 }); - b = {"x" : 3 }; - Object.setPrototypeOf(a, b); - tab = []; - for(i in a) { - tab.push(i); - } - assert(tab.toString(), "1,y", "for_in"); - - /* array optimization */ - a = []; - for(i = 0; i < 10; i++) - a.push(i); - tab = []; - for(i in a) { - tab.push(i); - } - assert(tab.toString(), "0,1,2,3,4,5,6,7,8,9", "for_in"); - - /* iterate with a field */ - a={x:0}; - tab = []; - for(a.x in {x:1, y: 2}) { - tab.push(a.x); - } - assert(tab.toString(), "x,y", "for_in"); - - /* iterate with a variable field */ - a=[0]; - tab = []; - for(a[0] in {x:1, y: 2}) { - tab.push(a[0]); - } - assert(tab.toString(), "x,y", "for_in"); - - /* variable definition in the for in */ - tab = []; - for(var j in {x:1, y: 2}) { - tab.push(j); - } - assert(tab.toString(), "x,y", "for_in"); - - /* variable assigment in the for in */ - tab = []; - for(var k = 2 in {x:1, y: 2}) { - tab.push(k); - } - assert(tab.toString(), "x,y", "for_in"); -} - -function test_for_in2() -{ - var i; - tab = []; - for(i in {x:1, y: 2, z:3}) { - if (i === "y") - continue; - tab.push(i); - } - assert(tab.toString() == "x,z"); - - tab = []; - for(i in {x:1, y: 2, z:3}) { - if (i === "z") - break; - tab.push(i); - } - assert(tab.toString() == "x,y"); -} - -function test_for_break() -{ - var i, c; - c = 0; - L1: for(i = 0; i < 3; i++) { - c++; - if (i == 0) - continue; - while (1) { - break L1; - } - } - assert(c === 2 && i === 1); -} - -function test_switch1() -{ - var i, a, s; - s = ""; - for(i = 0; i < 3; i++) { - a = "?"; - switch(i) { - case 0: - a = "a"; - break; - case 1: - a = "b"; - break; - default: - a = "c"; - break; - } - s += a; - } - assert(s === "abc" && i === 3); -} - -function test_switch2() -{ - var i, a, s; - s = ""; - for(i = 0; i < 4; i++) { - a = "?"; - switch(i) { - case 0: - a = "a"; - break; - case 1: - a = "b"; - break; - case 2: - continue; - default: - a = "" + i; - break; - } - s += a; - } - assert(s === "ab3" && i === 4); -} - -function test_try_catch1() -{ - try { - throw "hello"; - } catch (e) { - assert(e, "hello", "catch"); - return; - } - assert(false, "catch"); -} - -function test_try_catch2() -{ - var a; - try { - a = 1; - } catch (e) { - a = 2; - } - assert(a, 1, "catch"); -} - -function test_try_catch3() -{ - var s; - s = ""; - try { - s += "t"; - } catch (e) { - s += "c"; - } finally { - s += "f"; - } - assert(s, "tf", "catch"); -} - -function test_try_catch4() -{ - var s; - s = ""; - try { - s += "t"; - throw "c"; - } catch (e) { - s += e; - } finally { - s += "f"; - } - assert(s, "tcf", "catch"); -} - -function test_try_catch5() -{ - var s; - s = ""; - for(;;) { - try { - s += "t"; - break; - s += "b"; - } finally { - s += "f"; - } - } - assert(s, "tf", "catch"); -} - -function test_try_catch6() -{ - function f() { - try { - s += 't'; - return 1; - } finally { - s += "f"; - } - } - var s = ""; - assert(f() === 1); - assert(s, "tf", "catch6"); -} - -function test_try_catch7() -{ - var s; - s = ""; - - try { - try { - s += "t"; - throw "a"; - } finally { - s += "f"; - } - } catch(e) { - s += e; - } finally { - s += "g"; - } - assert(s, "tfag", "catch"); -} - -function test_try_catch8() -{ - var i, s; - - s = ""; - for(var i in {x:1, y:2}) { - try { - s += i; - throw "a"; - } catch (e) { - s += e; - } finally { - s += "f"; - } - } - assert(s === "xafyaf"); -} - -test_while(); -test_while_break(); -test_do_while(); -test_for(); -test_for_break(); -test_switch1(); -test_switch2(); -test_for_in(); -test_for_in2(); - -test_try_catch1(); -test_try_catch2(); -test_try_catch3(); -test_try_catch4(); -test_try_catch5(); -test_try_catch6(); -test_try_catch7(); -test_try_catch8(); diff --git a/quickjs/tests/test_op_overloading.js b/quickjs/tests/test_op_overloading.js deleted file mode 100644 index d08a85e..0000000 --- a/quickjs/tests/test_op_overloading.js +++ /dev/null @@ -1,207 +0,0 @@ -"use strict"; - -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -/* operators overloading with Operators.create() */ -function test_operators_create() { - class Vec2 - { - constructor(x, y) { - this.x = x; - this.y = y; - } - static mul_scalar(p1, a) { - var r = new Vec2(); - r.x = p1.x * a; - r.y = p1.y * a; - return r; - } - toString() { - return "Vec2(" + this.x + "," + this.y + ")"; - } - } - - Vec2.prototype[Symbol.operatorSet] = Operators.create( - { - "+"(p1, p2) { - var r = new Vec2(); - r.x = p1.x + p2.x; - r.y = p1.y + p2.y; - return r; - }, - "-"(p1, p2) { - var r = new Vec2(); - r.x = p1.x - p2.x; - r.y = p1.y - p2.y; - return r; - }, - "=="(a, b) { - return a.x == b.x && a.y == b.y; - }, - "<"(a, b) { - var r; - /* lexicographic order */ - if (a.x == b.x) - r = (a.y < b.y); - else - r = (a.x < b.x); - return r; - }, - "++"(a) { - var r = new Vec2(); - r.x = a.x + 1; - r.y = a.y + 1; - return r; - } - }, - { - left: Number, - "*"(a, b) { - return Vec2.mul_scalar(b, a); - } - }, - { - right: Number, - "*"(a, b) { - return Vec2.mul_scalar(a, b); - } - }); - - var a = new Vec2(1, 2); - var b = new Vec2(3, 4); - var r; - - r = a * 2 + 3 * b; - assert(r.x === 11 && r.y === 16); - assert(a == a, true); - assert(a == b, false); - assert(a != a, false); - assert(a < b, true); - assert(a <= b, true); - assert(b < a, false); - assert(b <= a, false); - assert(a <= a, true); - assert(a >= a, true); - a++; - assert(a.x === 2 && a.y === 3); - r = ++a; - assert(a.x === 3 && a.y === 4); - assert(r === a); -} - -/* operators overloading thru inheritance */ -function test_operators() -{ - var Vec2; - - function mul_scalar(p1, a) { - var r = new Vec2(); - r.x = p1.x * a; - r.y = p1.y * a; - return r; - } - - var vec2_ops = Operators({ - "+"(p1, p2) { - var r = new Vec2(); - r.x = p1.x + p2.x; - r.y = p1.y + p2.y; - return r; - }, - "-"(p1, p2) { - var r = new Vec2(); - r.x = p1.x - p2.x; - r.y = p1.y - p2.y; - return r; - }, - "=="(a, b) { - return a.x == b.x && a.y == b.y; - }, - "<"(a, b) { - var r; - /* lexicographic order */ - if (a.x == b.x) - r = (a.y < b.y); - else - r = (a.x < b.x); - return r; - }, - "++"(a) { - var r = new Vec2(); - r.x = a.x + 1; - r.y = a.y + 1; - return r; - } - }, - { - left: Number, - "*"(a, b) { - return mul_scalar(b, a); - } - }, - { - right: Number, - "*"(a, b) { - return mul_scalar(a, b); - } - }); - - Vec2 = class Vec2 extends vec2_ops - { - constructor(x, y) { - super(); - this.x = x; - this.y = y; - } - toString() { - return "Vec2(" + this.x + "," + this.y + ")"; - } - } - - var a = new Vec2(1, 2); - var b = new Vec2(3, 4); - var r; - - r = a * 2 + 3 * b; - assert(r.x === 11 && r.y === 16); - assert(a == a, true); - assert(a == b, false); - assert(a != a, false); - assert(a < b, true); - assert(a <= b, true); - assert(b < a, false); - assert(b <= a, false); - assert(a <= a, true); - assert(a >= a, true); - a++; - assert(a.x === 2 && a.y === 3); - r = ++a; - assert(a.x === 3 && a.y === 4); - assert(r === a); -} - -function test_default_op() -{ - assert(Object(1) + 2, 3); - assert(Object(1) + true, 2); - assert(-Object(1), -1); -} - -test_operators_create(); -test_operators(); -test_default_op(); diff --git a/quickjs/tests/test_qjscalc.js b/quickjs/tests/test_qjscalc.js deleted file mode 100644 index 1483466..0000000 --- a/quickjs/tests/test_qjscalc.js +++ /dev/null @@ -1,256 +0,0 @@ -"use math"; -"use strict"; - -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -function assertThrows(err, func) -{ - var ex; - ex = false; - try { - func(); - } catch(e) { - ex = true; - assert(e instanceof err); - } - assert(ex, true, "exception expected"); -} - -// load more elaborate version of assert if available -try { __loadScript("test_assert.js"); } catch(e) {} - -/*----------------*/ - -function pow(a, n) -{ - var r, i; - r = 1; - for(i = 0; i < n; i++) - r *= a; - return r; -} - -function test_integer() -{ - var a, r; - a = pow(3, 100); - assert((a - 1) != a); - assert(a == 515377520732011331036461129765621272702107522001); - assert(a == 0x5a4653ca673768565b41f775d6947d55cf3813d1); - assert(Integer.isInteger(1) === true); - assert(Integer.isInteger(1.0) === false); - - assert(Integer.floorLog2(0) === -1); - assert(Integer.floorLog2(7) === 2); - - r = 1 << 31; - assert(r, 2147483648, "1 << 31 === 2147483648"); - - r = 1 << 32; - assert(r, 4294967296, "1 << 32 === 4294967296"); - - r = (1 << 31) < 0; - assert(r, false, "(1 << 31) < 0 === false"); - - assert(typeof 1 === "number"); - assert(typeof 9007199254740991 === "number"); - assert(typeof 9007199254740992 === "bigint"); -} - -function test_float() -{ - assert(typeof 1.0 === "bigfloat"); - assert(1 == 1.0); - assert(1 !== 1.0); -} - -/* jscalc tests */ - -function test_modulo() -{ - var i, p, a, b; - - /* Euclidian modulo operator */ - assert((-3) % 2 == 1); - assert(3 % (-2) == 1); - - p = 101; - for(i = 1; i < p; i++) { - a = Integer.invmod(i, p); - assert(a >= 0 && a < p); - assert((i * a) % p == 1); - } - - assert(Integer.isPrime(2^107-1)); - assert(!Integer.isPrime((2^107-1) * (2^89-1))); - a = Integer.factor((2^89-1)*2^3*11*13^2*1009); - assert(a == [ 2,2,2,11,13,13,1009,618970019642690137449562111 ]); -} - -function test_fraction() -{ - assert((1/3 + 1).toString(), "4/3") - assert((2/3)^30, 1073741824/205891132094649); - assert(1/3 < 2/3); - assert(1/3 < 1); - assert(1/3 == 1.0/3); - assert(1.0/3 < 2/3); -} - -function test_mod() -{ - var a, b, p; - - a = Mod(3, 101); - b = Mod(-1, 101); - assert((a + b) == Mod(2, 101)); - assert(a ^ 100 == Mod(1, 101)); - - p = 2 ^ 607 - 1; /* mersenne prime */ - a = Mod(3, p) ^ (p - 1); - assert(a == Mod(1, p)); -} - -function test_polynomial() -{ - var a, b, q, r, t, i; - a = (1 + X) ^ 4; - assert(a == X^4+4*X^3+6*X^2+4*X+1); - - r = (1 + X); - q = (1+X+X^2); - b = (1 - X^2); - a = q * b + r; - t = Polynomial.divrem(a, b); - assert(t[0] == q); - assert(t[1] == r); - - a = 1 + 2*X + 3*X^2; - assert(a.apply(0.1) == 1.23); - - a = 1-2*X^2+2*X^3; - assert(deriv(a) == (6*X^2-4*X)); - assert(deriv(integ(a)) == a); - - a = (X-1)*(X-2)*(X-3)*(X-4)*(X-0.1); - r = polroots(a); - for(i = 0; i < r.length; i++) { - b = abs(a.apply(r[i])); - assert(b <= 1e-13); - } -} - -function test_poly_mod() -{ - var a, p; - - /* modulo using polynomials */ - p = X^2 + X + 1; - a = PolyMod(3+X, p) ^ 10; - assert(a == PolyMod(-3725*X-18357, p)); - - a = PolyMod(1/X, 1+X^2); - assert(a == PolyMod(-X, X^2+1)); -} - -function test_rfunc() -{ - var a; - a = (X+1)/((X+1)*(X-1)); - assert(a == 1/(X-1)); - a = (X + 2) / (X - 2); - assert(a.apply(1/3) == -7/5); - - assert(deriv((X^2-X+1)/(X-1)) == (X^2-2*X)/(X^2-2*X+1)); -} - -function test_series() -{ - var a, b; - a = 1+X+O(X^5); - b = a.inverse(); - assert(b == 1-X+X^2-X^3+X^4+O(X^5)); - assert(deriv(b) == -1+2*X-3*X^2+4*X^3+O(X^4)); - assert(deriv(integ(b)) == b); - - a = Series(1/(1-X), 5); - assert(a == 1+X+X^2+X^3+X^4+O(X^5)); - b = a.apply(0.1); - assert(b == 1.1111); - - assert(exp(3*X^2+O(X^10)) == 1+3*X^2+9/2*X^4+9/2*X^6+27/8*X^8+O(X^10)); - assert(sin(X+O(X^6)) == X-1/6*X^3+1/120*X^5+O(X^6)); - assert(cos(X+O(X^6)) == 1-1/2*X^2+1/24*X^4+O(X^6)); - assert(tan(X+O(X^8)) == X+1/3*X^3+2/15*X^5+17/315*X^7+O(X^8)); - assert((1+X+O(X^6))^(2+X) == 1+2*X+2*X^2+3/2*X^3+5/6*X^4+5/12*X^5+O(X^6)); -} - -function test_matrix() -{ - var a, b, r; - a = [[1, 2],[3, 4]]; - b = [3, 4]; - r = a * b; - assert(r == [11, 25]); - r = (a^-1) * 2; - assert(r == [[-4, 2],[3, -1]]); - - assert(norm2([1,2,3]) == 14); - - assert(diag([1,2,3]) == [ [ 1, 0, 0 ], [ 0, 2, 0 ], [ 0, 0, 3 ] ]); - assert(trans(a) == [ [ 1, 3 ], [ 2, 4 ] ]); - assert(trans([1,2,3]) == [[1,2,3]]); - assert(trace(a) == 5); - - assert(charpoly(Matrix.hilbert(4)) == X^4-176/105*X^3+3341/12600*X^2-41/23625*X+1/6048000); - assert(det(Matrix.hilbert(4)) == 1/6048000); - - a = [[1,2,1],[-2,-3,1],[3,5,0]]; - assert(rank(a) == 2); - assert(ker(a) == [ [ 5 ], [ -3 ], [ 1 ] ]); - - assert(dp([1, 2, 3], [3, -4, -7]) === -26); - assert(cp([1, 2, 3], [3, -4, -7]) == [ -2, 16, -10 ]); -} - -function assert_eq(a, ref) -{ - assert(abs(a / ref - 1.0) <= 1e-15); -} - -function test_trig() -{ - assert_eq(sin(1/2), 0.479425538604203); - assert_eq(sin(2+3*I), 9.154499146911428-4.168906959966565*I); - assert_eq(cos(2+3*I), -4.189625690968807-9.109227893755337*I); - assert_eq((2+0.5*I)^(1.1-0.5*I), 2.494363021357619-0.23076804554558092*I); - assert_eq(sqrt(2*I), 1 + I); -} - -test_integer(); -test_float(); - -test_modulo(); -test_fraction(); -test_mod(); -test_polynomial(); -test_poly_mod(); -test_rfunc(); -test_series(); -test_matrix(); -test_trig(); diff --git a/quickjs/tests/test_std.js b/quickjs/tests/test_std.js deleted file mode 100644 index 3ea6e34..0000000 --- a/quickjs/tests/test_std.js +++ /dev/null @@ -1,281 +0,0 @@ -import * as std from "std"; -import * as os from "os"; - -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -// load more elaborate version of assert if available -try { std.loadScript("test_assert.js"); } catch(e) {} - -/*----------------*/ - -function test_printf() -{ - assert(std.sprintf("a=%d s=%s", 123, "abc"), "a=123 s=abc"); - assert(std.sprintf("%010d", 123), "0000000123"); - assert(std.sprintf("%x", -2), "fffffffe"); - assert(std.sprintf("%lx", -2), "fffffffffffffffe"); - assert(std.sprintf("%10.1f", 2.1), " 2.1"); - assert(std.sprintf("%*.*f", 10, 2, -2.13), " -2.13"); - assert(std.sprintf("%#lx", 0x7fffffffffffffffn), "0x7fffffffffffffff"); -} - -function test_file1() -{ - var f, len, str, size, buf, ret, i, str1; - - f = std.tmpfile(); - str = "hello world\n"; - f.puts(str); - - f.seek(0, std.SEEK_SET); - str1 = f.readAsString(); - assert(str1 === str); - - f.seek(0, std.SEEK_END); - size = f.tell(); - assert(size === str.length); - - f.seek(0, std.SEEK_SET); - - buf = new Uint8Array(size); - ret = f.read(buf.buffer, 0, size); - assert(ret === size); - for(i = 0; i < size; i++) - assert(buf[i] === str.charCodeAt(i)); - - f.close(); -} - -function test_file2() -{ - var f, str, i, size; - f = std.tmpfile(); - str = "hello world\n"; - size = str.length; - for(i = 0; i < size; i++) - f.putByte(str.charCodeAt(i)); - f.seek(0, std.SEEK_SET); - for(i = 0; i < size; i++) { - assert(str.charCodeAt(i) === f.getByte()); - } - assert(f.getByte() === -1); - f.close(); -} - -function test_getline() -{ - var f, line, line_count, lines, i; - - lines = ["hello world", "line 1", "line 2" ]; - f = std.tmpfile(); - for(i = 0; i < lines.length; i++) { - f.puts(lines[i], "\n"); - } - - f.seek(0, std.SEEK_SET); - assert(!f.eof()); - line_count = 0; - for(;;) { - line = f.getline(); - if (line === null) - break; - assert(line == lines[line_count]); - line_count++; - } - assert(f.eof()); - assert(line_count === lines.length); - - f.close(); -} - -function test_popen() -{ - var str, f, fname = "tmp_file.txt"; - var content = "hello world"; - - f = std.open(fname, "w"); - f.puts(content); - f.close(); - - /* test loadFile */ - assert(std.loadFile(fname), content); - - /* execute the 'cat' shell command */ - f = std.popen("cat " + fname, "r"); - str = f.readAsString(); - f.close(); - - assert(str, content); - - os.remove(fname); -} - -function test_ext_json() -{ - var expected, input, obj; - expected = '{"x":false,"y":true,"z2":null,"a":[1,8,160],"s":"str"}'; - input = `{ "x":false, /*comments are allowed */ - "y":true, // also a comment - z2:null, // unquoted property names - "a":[+1,0o10,0xa0,], // plus prefix, octal, hexadecimal - "s":"str",} // trailing comma in objects and arrays - `; - obj = std.parseExtJSON(input); - assert(JSON.stringify(obj), expected); -} - -function test_os() -{ - var fd, fpath, fname, fdir, buf, buf2, i, files, err, fdate, st, link_path; - - assert(os.isatty(0)); - - fdir = "test_tmp_dir"; - fname = "tmp_file.txt"; - fpath = fdir + "/" + fname; - link_path = fdir + "/test_link"; - - os.remove(link_path); - os.remove(fpath); - os.remove(fdir); - - err = os.mkdir(fdir, 0o755); - assert(err === 0); - - fd = os.open(fpath, os.O_RDWR | os.O_CREAT | os.O_TRUNC); - assert(fd >= 0); - - buf = new Uint8Array(10); - for(i = 0; i < buf.length; i++) - buf[i] = i; - assert(os.write(fd, buf.buffer, 0, buf.length) === buf.length); - - assert(os.seek(fd, 0, std.SEEK_SET) === 0); - buf2 = new Uint8Array(buf.length); - assert(os.read(fd, buf2.buffer, 0, buf2.length) === buf2.length); - - for(i = 0; i < buf.length; i++) - assert(buf[i] == buf2[i]); - - if (typeof BigInt !== "undefined") { - assert(os.seek(fd, BigInt(6), std.SEEK_SET), BigInt(6)); - assert(os.read(fd, buf2.buffer, 0, 1) === 1); - assert(buf[6] == buf2[0]); - } - - assert(os.close(fd) === 0); - - [files, err] = os.readdir(fdir); - assert(err, 0); - assert(files.indexOf(fname) >= 0); - - fdate = 10000; - - err = os.utimes(fpath, fdate, fdate); - assert(err, 0); - - [st, err] = os.stat(fpath); - assert(err, 0); - assert(st.mode & os.S_IFMT, os.S_IFREG); - assert(st.mtime, fdate); - - err = os.symlink(fname, link_path); - assert(err === 0); - - [st, err] = os.lstat(link_path); - assert(err, 0); - assert(st.mode & os.S_IFMT, os.S_IFLNK); - - [buf, err] = os.readlink(link_path); - assert(err, 0); - assert(buf, fname); - - assert(os.remove(link_path) === 0); - - [buf, err] = os.getcwd(); - assert(err, 0); - - [buf2, err] = os.realpath("."); - assert(err, 0); - - assert(buf, buf2); - - assert(os.remove(fpath) === 0); - - fd = os.open(fpath, os.O_RDONLY); - assert(fd < 0); - - assert(os.remove(fdir) === 0); -} - -function test_os_exec() -{ - var ret, fds, pid, f, status; - - ret = os.exec(["true"]); - assert(ret, 0); - - ret = os.exec(["/bin/sh", "-c", "exit 1"], { usePath: false }); - assert(ret, 1); - - fds = os.pipe(); - pid = os.exec(["sh", "-c", "echo $FOO"], { - stdout: fds[1], - block: false, - env: { FOO: "hello" }, - } ); - assert(pid >= 0); - os.close(fds[1]); /* close the write end (as it is only in the child) */ - f = std.fdopen(fds[0], "r"); - assert(f.getline(), "hello"); - assert(f.getline(), null); - f.close(); - [ret, status] = os.waitpid(pid, 0); - assert(ret, pid); - assert(status & 0x7f, 0); /* exited */ - assert(status >> 8, 0); /* exit code */ - - pid = os.exec(["cat"], { block: false } ); - assert(pid >= 0); - os.kill(pid, os.SIGQUIT); - [ret, status] = os.waitpid(pid, 0); - assert(ret, pid); - assert(status & 0x7f, os.SIGQUIT); -} - -function test_timer() -{ - var th, i; - - /* just test that a timer can be inserted and removed */ - th = []; - for(i = 0; i < 3; i++) - th[i] = os.setTimeout(function () { }, 1000); - for(i = 0; i < 3; i++) - os.clearTimeout(th[i]); -} - -test_printf(); -test_file1(); -test_file2(); -test_getline(); -test_popen(); -test_os(); -test_os_exec(); -test_timer(); -test_ext_json(); diff --git a/quickjs/tests/test_worker.js b/quickjs/tests/test_worker.js deleted file mode 100644 index 4b52bf8..0000000 --- a/quickjs/tests/test_worker.js +++ /dev/null @@ -1,62 +0,0 @@ -/* os.Worker API test */ -import * as std from "std"; -import * as os from "os"; - -function assert(actual, expected, message) { - if (arguments.length == 1) - expected = true; - - if (actual === expected) - return; - - if (actual !== null && expected !== null - && typeof actual == 'object' && typeof expected == 'object' - && actual.toString() === expected.toString()) - return; - - throw Error("assertion failed: got |" + actual + "|" + - ", expected |" + expected + "|" + - (message ? " (" + message + ")" : "")); -} - -var worker; - -function test_worker() -{ - var counter; - - worker = new os.Worker("./test_worker_module.js"); - - counter = 0; - worker.onmessage = function (e) { - var ev = e.data; -// print("recv", JSON.stringify(ev)); - switch(ev.type) { - case "num": - assert(ev.num, counter); - counter++; - if (counter == 10) { - /* test SharedArrayBuffer modification */ - let sab = new SharedArrayBuffer(10); - let buf = new Uint8Array(sab); - worker.postMessage({ type: "sab", buf: buf }); - } - break; - case "sab_done": - { - let buf = ev.buf; - /* check that the SharedArrayBuffer was modified */ - assert(buf[2], 10); - worker.postMessage({ type: "abort" }); - } - break; - case "done": - /* terminate */ - worker.onmessage = null; - break; - } - }; -} - - -test_worker(); diff --git a/quickjs/tests/test_worker_module.js b/quickjs/tests/test_worker_module.js deleted file mode 100644 index c783e1f..0000000 --- a/quickjs/tests/test_worker_module.js +++ /dev/null @@ -1,31 +0,0 @@ -/* Worker code for test_worker.js */ -import * as std from "std"; -import * as os from "os"; - -var parent = os.Worker.parent; - -function handle_msg(e) { - var ev = e.data; - // print("child_recv", JSON.stringify(ev)); - switch(ev.type) { - case "abort": - parent.postMessage({ type: "done" }); - break; - case "sab": - /* modify the SharedArrayBuffer */ - ev.buf[2] = 10; - parent.postMessage({ type: "sab_done", buf: ev.buf }); - break; - } -} - -function worker_main() { - var i; - - parent.onmessage = handle_msg; - for(i = 0; i < 10; i++) { - parent.postMessage({ type: "num", num: i }); - } -} - -worker_main(); diff --git a/source/scripts/engine.js b/source/scripts/engine.js index b47d9f6..a6e7dbb 100644 --- a/source/scripts/engine.js +++ b/source/scripts/engine.js @@ -58,7 +58,7 @@ Cmdline.register_cmd("h", function() { Game.quit(); }, "Help."); -Cmdline.register_cmd("b", function() { cmd(124); Game.quit(); }, "Pack the game into the given name."); +Cmdline.register_cmd("b", function() { Log.warn("PACKING");cmd(124); Game.quit(); }, "Pack the game into the given name."); Cmdline.register_cmd("e", function(pawn) { run("scripts/editor.js");