Merge remote-tracking branch 'origin/js-def' into js-rm-modules

This commit is contained in:
2025-06-16 14:16:01 -05:00
12 changed files with 87 additions and 85 deletions

View File

@@ -42,34 +42,34 @@ for (let i = 0; i < 100; i++) {
// Calculate statistics
function getStats(arr) {
const avg = arr.reduce((a, b) => a + b) / arr.length;
const min = Math.min(...arr);
const max = Math.max(...arr);
def avg = arr.reduce((a, b) => a + b) / arr.length;
def min = Math.min(...arr);
def max = Math.max(...arr);
return { avg, min, max };
}
// Pretty print results
log.console("\n=== Performance Test Results (100 iterations) ===");
log.console("\nJSON Decoding (ms):");
const jsonDecStats = getStats(jsonDecodeTimes);
def jsonDecStats = getStats(jsonDecodeTimes);
log.console(`Average: ${jsonDecStats.avg.toFixed(2)} ms`);
log.console(`Min: ${jsonDecStats.min.toFixed(2)} ms`);
log.console(`Max: ${jsonDecStats.max.toFixed(2)} ms`);
log.console("\nJSON Encoding (ms):");
const jsonEncStats = getStats(jsonEncodeTimes);
def jsonEncStats = getStats(jsonEncodeTimes);
log.console(`Average: ${jsonEncStats.avg.toFixed(2)} ms`);
log.console(`Min: ${jsonEncStats.min.toFixed(2)} ms`);
log.console(`Max: ${jsonEncStats.max.toFixed(2)} ms`);
log.console("\nNOTA Encoding (ms):");
const notaEncStats = getStats(notaEncodeTimes);
def notaEncStats = getStats(notaEncodeTimes);
log.console(`Average: ${notaEncStats.avg.toFixed(2)} ms`);
log.console(`Min: ${notaEncStats.min.toFixed(2)} ms`);
log.console(`Max: ${notaEncStats.max.toFixed(2)} ms`);
log.console("\nNOTA Decoding (ms):");
const notaDecStats = getStats(notaDecodeTimes);
def notaDecStats = getStats(notaDecodeTimes);
log.console(`Average: ${notaDecStats.avg.toFixed(2)} ms`);
log.console(`Min: ${notaDecStats.min.toFixed(2)} ms`);
log.console(`Max: ${notaDecStats.max.toFixed(2)} ms`);

View File

@@ -36,7 +36,7 @@ function roundTripWota(value) {
// iterations: how many times to loop
//
// You can tweak these as you like for heavier or lighter tests.
const benchmarks = [
def benchmarks = [
{
name: "Small Integers",
data: [0, 42, -1, 2023],

View File

@@ -25,7 +25,7 @@ var scenario_name = arg[1];
// 1. Setup "libraries" array to easily switch among wota, nota, and json
////////////////////////////////////////////////////////////////////////////////
const libraries = [
def libraries = [
{
name: "wota",
encode: wota.encode,
@@ -62,7 +62,7 @@ const libraries = [
// Each scenario has { name, data, iterations }
////////////////////////////////////////////////////////////////////////////////
const benchmarks = [
def benchmarks = [
{
name: "empty",
data: [{}, {}, {}, {}],

View File

@@ -123,7 +123,7 @@ function make_handle(obj)
}
function wrapSurface(surf, maybeRect){
const h = make_handle(surf);
def h = make_handle(surf);
if(maybeRect) h.rect = maybeRect; /* honour frame sub-rect */
return h;
}
@@ -150,7 +150,7 @@ function decode_image(bytes, ext)
function create_image(path){
try{
const bytes = io.slurpbytes(path);
def bytes = io.slurpbytes(path);
let raw = decode_image(bytes, path.ext());
@@ -169,8 +169,8 @@ function create_image(path){
return makeAnim( wrapFrames(raw.frames), !!raw.loop );
/* ── Case D: ASE helpers returned { animName:{frames,loop}, … } ── */
const anims = {};
for(const [name, anim] of Object.entries(raw)){
def anims = {};
for(def [name, anim] of Object.entries(raw)){
if(anim && Array.isArray(anim.frames))
anims[name] = makeAnim( wrapFrames(anim.frames), !!anim.loop );
else if(anim && anim.surface) /* ase with flat surface */

View File

@@ -36,16 +36,16 @@ var geometry = use('geometry')
function updateCameraMatrix(camera, winW, winH) {
// world→NDC
const sx = 1 / camera.size[0];
const sy = 1 / camera.size[1];
const ox = camera.pos[0] - camera.size[0] * camera.anchor[0];
const oy = camera.pos[1] - camera.size[1] * camera.anchor[1];
def sx = 1 / camera.size[0];
def sy = 1 / camera.size[1];
def ox = camera.pos[0] - camera.size[0] * camera.anchor[0];
def oy = camera.pos[1] - camera.size[1] * camera.anchor[1];
// NDC→pixels
const vx = camera.viewport.x * winW;
const vy = camera.viewport.y * winH;
const vw = camera.viewport.width * winW;
const vh = camera.viewport.height * winH;
def vx = camera.viewport.x * winW;
def vy = camera.viewport.y * winH;
def vw = camera.viewport.width * winW;
def vh = camera.viewport.height * winH;
// final “mat” coefficients
// [ a 0 c ]
@@ -82,14 +82,14 @@ function screenToWorldPoint(pos, camera) {
//---- rectangle (two corner) ----
function worldToScreenRect(rect, camera) {
// map bottom-left and top-right
const x1 = camera.a * rect.x + camera.c;
const y1 = camera.e * rect.y + camera.f;
const x2 = camera.a * (rect.x + rect.width) + camera.c;
const y2 = camera.e * (rect.y + rect.height) + camera.f;
def x1 = camera.a * rect.x + camera.c;
def y1 = camera.e * rect.y + camera.f;
def x2 = camera.a * (rect.x + rect.width) + camera.c;
def y2 = camera.e * (rect.y + rect.height) + camera.f;
// pick mins and abs deltas
const x0 = x1 < x2 ? x1 : x2;
const y0 = y1 < y2 ? y1 : y2;
def x0 = x1 < x2 ? x1 : x2;
def y0 = y1 < y2 ? y1 : y2;
return {
x: x0,
y: y0,
@@ -335,7 +335,7 @@ function poll_input() {
// 2) helper to build & send a batch, then call done()
function create_batch(draw_cmds, done) {
const batch = [
def batch = [
{op:'set', prop:'drawColor', value:[0.1,0.1,0.15,1]},
{op:'clear'}
]
@@ -349,8 +349,8 @@ function create_batch(draw_cmds, done) {
)
send(video, {kind:'renderer', op:'batch', data:batch}, () => {
const now = time.number()
const dt = now - last_time
def now = time.number()
def dt = now - last_time
last_time = now
frames.push(dt)
@@ -376,7 +376,7 @@ function start_pipeline() {
function render_step() {
// a) fire off the next update→draw immediately
const dt = time.number() - last_time
def dt = time.number() - last_time
send(gameactor, {kind:'update', dt:1/60}, () =>
send(gameactor, {kind:'draw'}, cmds => pending_next = cmds)
)
@@ -390,8 +390,8 @@ function render_step() {
}
// d) schedule the next render step
const render_dur = time.number() - last_time
const wait = Math.max(0, 1/60 - ttr)
def render_dur = time.number() - last_time
def wait = Math.max(0, 1/60 - ttr)
$_.delay(render_step, 0)
})
}

View File

@@ -1,6 +1,6 @@
/* anim.js drop this at top of your script or in a module */
var Anim = (() => {
const DEFAULT_MIN = 1 / 60; /* 16 ms one frame */
def DEFAULT_MIN = 1 / 60; /* 16 ms one frame */
function play(source, loop=true){
return {
@@ -13,9 +13,9 @@ var Anim = (() => {
function update(a, dt){
a.timer += dt;
const frames = a.src.frames;
def frames = a.src.frames;
while(true){
const time = Math.max(frames[a.idx].time || 0, Anim.minDelay);
def time = Math.max(frames[a.idx].time || 0, Anim.minDelay);
if(a.timer < time) break; /* still on current frame */
a.timer -= time;
@@ -29,7 +29,7 @@ var Anim = (() => {
}
function current(a){ return a.src.frames[a.idx].image; }
function updateAll(arr, dt){ for(const a of arr) update(a, dt); }
function updateAll(arr, dt){ for(def a of arr) update(a, dt); }
function draw(a, pos, opt, pipe){
draw2d.image(current(a), pos, 0, [0,0], [0,0], opt, pipe);
}
@@ -60,10 +60,10 @@ var camera = {
}
/* ── load animations ───────────────────── */
const crab = gfx.texture('tests/crab'); // gif → Animation
const warrior = gfx.texture('tests/warrior'); // ase → {Original:Animation}
def crab = gfx.texture('tests/crab'); // gif → Animation
def warrior = gfx.texture('tests/warrior'); // ase → {Original:Animation}
const anims = [
def anims = [
Anim.play(crab), // crab.frames
Anim.play(warrior.Run) // warrior.Original.frames
];
@@ -76,8 +76,8 @@ Anim.minDelay = 1 / 100; // 10 ms, feel free to tune later
let last = os.now();
function loop(){
const now = os.now();
const dt = now - last; // real frame time
def now = os.now();
def dt = now - last; // real frame time
last = now;
Anim.updateAll(anims, dt);

View File

@@ -14,12 +14,12 @@
 Each factory returns a **requestor** function as described by the spec.
*/
const delay = arg[0] // may be undefined
def delay = arg[0] // may be undefined
// ———————————————————————————————————————— helpers
function make_reason (factory, excuse, evidence) {
const reason = new Error(`parseq.${factory}${excuse ? ': ' + excuse : ''}`)
def reason = new Error(`parseq.${factory}${excuse ? ': ' + excuse : ''}`)
reason.evidence = evidence
return reason
}
@@ -61,7 +61,7 @@ function run (factory, requestors, initial, action, time_limit, throttle = 0) {
function start_requestor (value) {
if (!cancel_list || next >= requestors.length) return
let idx = next++
const req = requestors[idx]
def req = requestors[idx]
try {
cancel_list[idx] = req(function req_cb (val, reason) {
@@ -86,7 +86,7 @@ function run (factory, requestors, initial, action, time_limit, throttle = 0) {
if (time_limit > 0) timer_cancel = schedule(() => cancel(make_reason(factory, 'Timeout.', time_limit)), time_limit)
}
const concurrent = throttle ? Math.min(throttle, requestors.length) : requestors.length
def concurrent = throttle ? Math.min(throttle, requestors.length) : requestors.length
for (let i = 0; i < concurrent; i++) start_requestor(initial)
return cancel
@@ -97,8 +97,8 @@ function run (factory, requestors, initial, action, time_limit, throttle = 0) {
function _normalize (collection, factory) {
if (Array.isArray(collection)) return { names: null, list: collection }
if (collection && typeof collection === 'object') {
const names = Object.keys(collection)
const list = names.map(k => collection[k]).filter(is_requestor)
def names = Object.keys(collection)
def list = names.map(k => collection[k]).filter(is_requestor)
return { names, list }
}
throw make_reason(factory, 'Expected array or record.', collection)
@@ -106,23 +106,23 @@ function _normalize (collection, factory) {
function _denormalize (names, list) {
if (!names) return list
const obj = Object.create(null)
def obj = Object.create(null)
names.forEach((k, i) => { obj[k] = list[i] })
return obj
}
function par_all (collection, time_limit, throttle) {
const factory = 'par_all'
const { names, list } = _normalize(collection, factory)
def factory = 'par_all'
def { names, list } = _normalize(collection, factory)
if (list.length === 0) return (cb, v) => cb(names ? {} : [])
check_requestors(list, factory)
return function par_all_req (cb, initial) {
check_callback(cb, factory)
let pending = list.length
const results = new Array(list.length)
def results = new Array(list.length)
const cancel = run(factory, list, initial, (val, reason, idx) => {
def cancel = run(factory, list, initial, (val, reason, idx) => {
if (val === undefined) {
cancel(reason)
return cb(undefined, reason)
@@ -136,17 +136,17 @@ function par_all (collection, time_limit, throttle) {
}
function par_any (collection, time_limit, throttle) {
const factory = 'par_any'
const { names, list } = _normalize(collection, factory)
def factory = 'par_any'
def { names, list } = _normalize(collection, factory)
if (list.length === 0) return (cb, v) => cb(names ? {} : [])
check_requestors(list, factory)
return function par_any_req (cb, initial) {
check_callback(cb, factory)
let pending = list.length
const successes = new Array(list.length)
def successes = new Array(list.length)
const cancel = run(factory, list, initial, (val, reason, idx) => {
def cancel = run(factory, list, initial, (val, reason, idx) => {
pending--
if (val !== undefined) successes[idx] = val
if (successes.some(v => v !== undefined)) {
@@ -161,7 +161,7 @@ function par_any (collection, time_limit, throttle) {
}
function race (list, time_limit, throttle) {
const factory = throttle === 1 ? 'fallback' : 'race'
def factory = throttle === 1 ? 'fallback' : 'race'
if (!Array.isArray(list) || list.length === 0)
throw make_reason(factory, 'No requestors.')
check_requestors(list, factory)
@@ -169,7 +169,7 @@ function race (list, time_limit, throttle) {
return function race_req (cb, initial) {
check_callback(cb, factory)
let done = false
const cancel = run(factory, list, initial, (val, reason, idx) => {
def cancel = run(factory, list, initial, (val, reason, idx) => {
if (done) return
if (val !== undefined) {
done = true
@@ -190,7 +190,7 @@ function fallback (list, time_limit) {
}
function sequence (list, time_limit) {
const factory = 'sequence'
def factory = 'sequence'
if (!Array.isArray(list)) throw make_reason(factory, 'Not an array.', list)
check_requestors(list, factory)
if (list.length === 0) return (cb, v) => cb(v)

View File

@@ -33,6 +33,7 @@ DEF(if, "if")
DEF(else, "else")
DEF(return, "return")
DEF(var, "var")
DEF(def, "def")
DEF(this, "this")
DEF(delete, "delete")
DEF(void, "void")

View File

@@ -18183,6 +18183,7 @@ enum {
TOK_ELSE,
TOK_RETURN,
TOK_VAR,
TOK_DEF,
TOK_THIS,
TOK_DELETE,
TOK_VOID,
@@ -21624,14 +21625,14 @@ static __exception int js_define_var(JSParseState *s, JSAtom name, int tok)
return js_parse_error(s, "invalid variable name in strict mode");
}
if (name == JS_ATOM_let
&& (tok == TOK_LET || tok == TOK_CONST)) {
&& (tok == TOK_LET || tok == TOK_DEF)) {
return js_parse_error(s, "invalid lexical variable name");
}
switch(tok) {
case TOK_LET:
var_def_type = JS_VAR_DEF_LET;
break;
case TOK_CONST:
case TOK_DEF:
var_def_type = JS_VAR_DEF_CONST;
break;
case TOK_VAR:
@@ -21693,7 +21694,7 @@ duplicate:
return js_parse_error(s, "duplicate parameter names not allowed in this context");
}
/* tok = TOK_VAR, TOK_LET or TOK_CONST. Return whether a reference
/* tok = TOK_VAR, TOK_LET or TOK_DEF. Return whether a reference
must be taken to the variable for proper 'with' or global variable
evaluation */
/* Note: this function is needed only because variable references are
@@ -22024,7 +22025,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
/* store value into lvalue object */
put_lvalue(s, opcode, scope, var_name, label_lvalue,
PUT_LVALUE_NOKEEP_DEPTH,
(tok == TOK_CONST || tok == TOK_LET));
(tok == TOK_DEF || tok == TOK_LET));
if (s->token.val == '}')
break;
/* accept a trailing comma before the '}' */
@@ -22138,7 +22139,7 @@ static int js_parse_destructuring_element(JSParseState *s, int tok, int is_arg,
/* store value into lvalue object */
put_lvalue(s, opcode, scope, var_name,
label_lvalue, PUT_LVALUE_NOKEEP_DEPTH,
(tok == TOK_CONST || tok == TOK_LET));
(tok == TOK_DEF || tok == TOK_LET));
}
if (s->token.val == ']')
break;
@@ -23490,7 +23491,7 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
return js_parse_error_reserved_identifier(s);
}
name = JS_DupAtom(ctx, s->token.u.ident.atom);
if (name == JS_ATOM_let && (tok == TOK_LET || tok == TOK_CONST)) {
if (name == JS_ATOM_let && (tok == TOK_LET || tok == TOK_DEF)) {
js_parse_error(s, "'let' is not a valid lexical identifier");
goto var_error;
}
@@ -23523,13 +23524,13 @@ static __exception int js_parse_var(JSParseState *s, int parse_flags, int tok,
if (js_parse_assign_expr2(s, parse_flags))
goto var_error;
set_object_name(s, name);
emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ?
emit_op(s, (tok == TOK_DEF || tok == TOK_LET) ?
OP_scope_put_var_init : OP_scope_put_var);
emit_atom(s, name);
emit_u16(s, fd->scope_level);
}
} else {
if (tok == TOK_CONST) {
if (tok == TOK_DEF) {
js_parse_error(s, "missing initializer for const variable");
goto var_error;
}
@@ -23665,7 +23666,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name)
default:
return -1;
}
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) {
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_DEF) {
if (next_token(s))
return -1;
@@ -23688,7 +23689,7 @@ static __exception int js_parse_for_in_of(JSParseState *s, int label_name)
JS_FreeAtom(s->ctx, var_name);
return -1;
}
emit_op(s, (tok == TOK_CONST || tok == TOK_LET) ?
emit_op(s, (tok == TOK_DEF || tok == TOK_LET) ?
OP_scope_put_var_init : OP_scope_put_var);
emit_atom(s, var_name);
emit_u16(s, fd->scope_level);
@@ -23929,7 +23930,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
}
break;
case TOK_LET:
case TOK_CONST:
case TOK_DEF:
haslet:
if (!(decl_mask & DECL_MASK_OTHER)) {
js_parse_error(s, "lexical declarations can't appear in single-statement context");
@@ -24088,7 +24089,7 @@ static __exception int js_parse_statement_or_decl(JSParseState *s,
default:
goto fail;
}
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_CONST) {
if (tok == TOK_VAR || tok == TOK_LET || tok == TOK_DEF) {
if (next_token(s))
goto fail;
if (js_parse_var(s, FALSE, tok, FALSE))
@@ -28448,7 +28449,7 @@ static __exception int js_parse_directives(JSParseState *s)
case TOK_TRY:
case TOK_FUNCTION:
case TOK_DEBUGGER:
case TOK_CONST:
case TOK_DEF:
case TOK_ENUM:
case TOK_EXPORT:
case TOK_IMPORT:

View File

@@ -27,7 +27,7 @@ function deepCompare(expected, actual, path = '') {
if (isNaN(expected) && isNaN(actual))
return { passed: true, messages: [] };
const diff = Math.abs(expected - actual);
def diff = Math.abs(expected - actual);
if (diff <= EPSILON)
return { passed: true, messages: [] };
@@ -41,8 +41,8 @@ function deepCompare(expected, actual, path = '') {
}
if (expected instanceof ArrayBuffer && actual instanceof ArrayBuffer) {
const expArray = Array.from(new Uint8Array(expected));
const actArray = Array.from(new Uint8Array(actual));
def expArray = Array.from(new Uint8Array(expected));
def actArray = Array.from(new Uint8Array(actual));
return deepCompare(expArray, actArray, path);
}
@@ -57,7 +57,7 @@ function deepCompare(expected, actual, path = '') {
};
let messages = [];
for (let i = 0; i < expected.length; i++) {
const result = deepCompare(expected[i], actual[i], `${path}[${i}]`);
def result = deepCompare(expected[i], actual[i], `${path}[${i}]`);
if (!result.passed) messages.push(...result.messages);
}
return { passed: messages.length === 0, messages };
@@ -65,8 +65,8 @@ function deepCompare(expected, actual, path = '') {
if (typeof expected === 'object' && expected !== null &&
typeof actual === 'object' && actual !== null) {
const expKeys = Object.keys(expected).sort();
const actKeys = Object.keys(actual).sort();
def expKeys = Object.keys(expected).sort();
def actKeys = Object.keys(actual).sort();
if (JSON.stringify(expKeys) !== JSON.stringify(actKeys))
return {
passed: false,
@@ -74,7 +74,7 @@ function deepCompare(expected, actual, path = '') {
};
let messages = [];
for (let key of expKeys) {
const result = deepCompare(expected[key], actual[key], `${path}.${key}`);
def result = deepCompare(expected[key], actual[key], `${path}.${key}`);
if (!result.passed) messages.push(...result.messages);
}
return { passed: messages.length === 0, messages };
@@ -228,11 +228,11 @@ for (let test of testCases) {
if (decoded instanceof ArrayBuffer)
decoded = Array.from(new Uint8Array(decoded));
if (expected && (expected.private || expected.system)) {
const key = expected.private ? 'private' : 'system';
def key = expected.private ? 'private' : 'system';
expected = { [key]: expected[key] };
}
const compareResult = deepCompare(expected, decoded);
def compareResult = deepCompare(expected, decoded);
if (!compareResult.passed) {
passed = false;
messages.push("Decoding failed:");

View File

@@ -100,7 +100,7 @@ send(ioguy, {
})
function strToArrayBuffer(binStr) {
const view = new Uint8Array(binStr.length);
def view = new Uint8Array(binStr.length);
for (let i = 0; i < binStr.length; i++)
view[i] = binStr.codePointAt(i) & 0xff; // mask keeps it 0-255
return view.buffer;

View File

@@ -16,7 +16,7 @@ var Blob = use('blob')
/* Helper utilities */
/*──────────────────────────────────────────────────────────────────────────*/
const EPSILON = 1e-12
def EPSILON = 1e-12
function stone_if_needed(b) { if (!stone.p(b)) stone(b) }