Merge branch 'mcode2' into mach
This commit is contained in:
30
fd.c
30
fd.c
@@ -504,7 +504,7 @@ JSC_SCALL(fd_readdir,
|
||||
ret = JS_NewArray(js);
|
||||
do {
|
||||
if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0) continue;
|
||||
JS_ArrayPush(js, ret,JS_NewString(js, ffd.cFileName));
|
||||
JS_ArrayPush(js, &ret, JS_NewString(js, ffd.cFileName));
|
||||
} while (FindNextFile(hFind, &ffd) != 0);
|
||||
FindClose(hFind);
|
||||
}
|
||||
@@ -516,7 +516,7 @@ JSC_SCALL(fd_readdir,
|
||||
ret = JS_NewArray(js);
|
||||
while ((dir = readdir(d)) != NULL) {
|
||||
if (strcmp(dir->d_name, ".") == 0 || strcmp(dir->d_name, "..") == 0) continue;
|
||||
JS_ArrayPush(js, ret, JS_NewString(js, dir->d_name));
|
||||
JS_ArrayPush(js, &ret, JS_NewString(js, dir->d_name));
|
||||
}
|
||||
closedir(d);
|
||||
} else {
|
||||
@@ -565,18 +565,22 @@ JSC_CCALL(fd_slurpwrite,
|
||||
if (!str) return JS_EXCEPTION;
|
||||
int fd = open(str, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd < 0) {
|
||||
ret = JS_ThrowInternalError(js, "open failed for %s: %s", str, strerror(errno));
|
||||
JS_FreeCString(js, str);
|
||||
return JS_ThrowInternalError(js, "open failed for %s: %s", str, strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ssize_t written = write(fd, data, len);
|
||||
close(fd);
|
||||
|
||||
if (written != (ssize_t)len) {
|
||||
ret = JS_ThrowInternalError(js, "write failed for %s: %s", str, strerror(errno));
|
||||
JS_FreeCString(js, str);
|
||||
return ret;
|
||||
}
|
||||
|
||||
JS_FreeCString(js, str);
|
||||
|
||||
if (written != (ssize_t)len)
|
||||
return JS_ThrowInternalError(js, "write failed for %s: %s", str, strerror(errno));
|
||||
|
||||
return JS_NULL;
|
||||
)
|
||||
|
||||
@@ -664,17 +668,21 @@ JSC_CCALL(fd_realpath,
|
||||
#ifdef _WIN32
|
||||
char resolved[PATH_MAX];
|
||||
DWORD len = GetFullPathNameA(path, PATH_MAX, resolved, NULL);
|
||||
JS_FreeCString(js, path);
|
||||
if (len == 0 || len >= PATH_MAX) {
|
||||
return JS_ThrowInternalError(js, "realpath failed for %s: %s", path, strerror(errno));
|
||||
JSValue err = JS_ThrowInternalError(js, "realpath failed for %s: %s", path, strerror(errno));
|
||||
JS_FreeCString(js, path);
|
||||
return err;
|
||||
}
|
||||
JS_FreeCString(js, path);
|
||||
return JS_NewString(js, resolved);
|
||||
#else
|
||||
char *resolved = realpath(path, NULL);
|
||||
JS_FreeCString(js, path);
|
||||
if (!resolved) {
|
||||
return JS_ThrowInternalError(js, "realpath failed for %s: %s", path, strerror(errno));
|
||||
JSValue err = JS_ThrowInternalError(js, "realpath failed for %s: %s", path, strerror(errno));
|
||||
JS_FreeCString(js, path);
|
||||
return err;
|
||||
}
|
||||
JS_FreeCString(js, path);
|
||||
JSValue result = JS_NewString(js, resolved);
|
||||
free(resolved);
|
||||
return result;
|
||||
|
||||
2
fd.cm
2
fd.cm
@@ -1,4 +1,4 @@
|
||||
var fd = this
|
||||
var fd = native
|
||||
var wildstar = use('wildstar')
|
||||
|
||||
function last_pos(str, sep) {
|
||||
|
||||
@@ -242,7 +242,7 @@ var script = null
|
||||
var ast = null
|
||||
|
||||
if (args != null) {
|
||||
// CLI mode — run script directly
|
||||
// CLI mode — parse args
|
||||
program = args[0]
|
||||
_j = 1
|
||||
while (_j < length(args)) {
|
||||
@@ -250,11 +250,11 @@ if (args != null) {
|
||||
_j = _j + 1
|
||||
}
|
||||
|
||||
// Resolve script file: try .cm then .ce in CWD then core_path
|
||||
script_file = program
|
||||
if (!ends_with(script_file, '.ce') && !ends_with(script_file, '.cm'))
|
||||
script_file = program + '.cm'
|
||||
|
||||
// Search CWD then core_path, trying .cm then .ce
|
||||
if (!fd.is_file(script_file))
|
||||
script_file = core_path + '/' + program + '.cm'
|
||||
if (!fd.is_file(script_file))
|
||||
@@ -262,9 +262,20 @@ if (args != null) {
|
||||
if (!fd.is_file(script_file))
|
||||
script_file = core_path + '/' + program + '.ce'
|
||||
|
||||
script = text(fd.slurp(script_file))
|
||||
ast = analyze(script, script_file)
|
||||
run_ast(program, ast, {use: use_fn, args: user_args, json: json})
|
||||
if (ends_with(script_file, '.ce')) {
|
||||
// Actor script — delegate to engine
|
||||
load_engine({
|
||||
os: os, actorsym: actorsym,
|
||||
init: {program: program, arg: user_args},
|
||||
core_path: core_path, shop_path: shop_path, json: json,
|
||||
analyze: analyze, run_ast_fn: run_ast
|
||||
})
|
||||
} else {
|
||||
// Module script — run directly
|
||||
script = text(fd.slurp(script_file))
|
||||
ast = analyze(script, script_file)
|
||||
run_ast(program, ast, {use: use_fn, args: user_args, json: json})
|
||||
}
|
||||
} else {
|
||||
// Actor spawn mode — load engine.cm with full actor env
|
||||
load_engine({
|
||||
|
||||
Binary file not shown.
@@ -56,9 +56,13 @@ var packages_path = shop_path ? shop_path + '/packages' : null
|
||||
var use_cache = {}
|
||||
use_cache['core/os'] = os
|
||||
|
||||
// Extra env properties added as engine initializes (log, runtime fns, etc.)
|
||||
var core_extras = {}
|
||||
|
||||
// Load a core module from the file system
|
||||
function use_core(path) {
|
||||
var cache_key = 'core/' + path
|
||||
var env = null
|
||||
if (use_cache[cache_key])
|
||||
return use_cache[cache_key]
|
||||
|
||||
@@ -67,10 +71,15 @@ function use_core(path) {
|
||||
var script = null
|
||||
var ast = null
|
||||
|
||||
// Build env: merge core_extras, include C embed as 'native' if available
|
||||
env = {use: use_core}
|
||||
arrfor(array(core_extras), function(k) { env[k] = core_extras[k] })
|
||||
if (sym) env.native = sym
|
||||
|
||||
// Check for pre-compiled .mach file first
|
||||
var mach_path = core_path + '/' + path + '.mach'
|
||||
if (fd.is_file(mach_path)) {
|
||||
result = mach_load(fd.slurp(mach_path), {use: use_core})
|
||||
result = mach_load(fd.slurp(mach_path), env)
|
||||
use_cache[cache_key] = result
|
||||
return result
|
||||
}
|
||||
@@ -80,7 +89,7 @@ function use_core(path) {
|
||||
if (fd.is_file(file_path)) {
|
||||
script = text(fd.slurp(file_path))
|
||||
ast = analyze(script, file_path)
|
||||
result = run_ast_fn('core:' + path, ast, {use: use_core})
|
||||
result = run_ast_fn('core:' + path, ast, env)
|
||||
use_cache[cache_key] = result
|
||||
return result
|
||||
}
|
||||
@@ -90,6 +99,9 @@ function use_core(path) {
|
||||
return sym
|
||||
}
|
||||
|
||||
// Load full modules via use_core (extends C embeds with .cm additions, and caches)
|
||||
fd = use_core('fd')
|
||||
use_core('js')
|
||||
var blob = use_core('blob')
|
||||
|
||||
function actor() {
|
||||
@@ -109,23 +121,7 @@ var REPLYTIMEOUT = 60 // seconds before replies are ignored
|
||||
|
||||
function caller_data(depth)
|
||||
{
|
||||
var _depth = depth == null ? 0 : depth
|
||||
var file = "nofile"
|
||||
var line = 0
|
||||
var md = null
|
||||
var m = null
|
||||
|
||||
var caller = array(Error().stack, "\n")[1+_depth]
|
||||
if (caller) {
|
||||
md = extract(caller, /\((.*)\:/)
|
||||
m = md ? md[1] : "SCRIPT"
|
||||
if (m) file = m
|
||||
md = extract(caller, /\:(\d*)\)/)
|
||||
m = md ? md[1] : 0
|
||||
if (m) line = m
|
||||
}
|
||||
|
||||
return {file,line}
|
||||
return {file: "nofile", line: 0}
|
||||
}
|
||||
|
||||
function console_rec(line, file, msg) {
|
||||
@@ -140,9 +136,7 @@ function log(name, args) {
|
||||
if (name == 'console') {
|
||||
os.print(console_rec(caller.line, caller.file, msg))
|
||||
} else if (name == 'error') {
|
||||
if (msg == null) msg = Error()
|
||||
if (is_proto(msg, Error))
|
||||
msg = msg.name + ": " + msg.message + "\n" + msg.stack
|
||||
if (msg == null) msg = "error"
|
||||
os.print(console_rec(caller.line, caller.file, msg))
|
||||
} else if (name == 'system') {
|
||||
msg = "[SYSTEM] " + msg
|
||||
@@ -166,7 +160,7 @@ function actor_die(err)
|
||||
if (overling) {
|
||||
if (err) {
|
||||
// with an err, this is a forceful disrupt
|
||||
reason = (is_proto(err, Error)) ? err.stack : err
|
||||
reason = err
|
||||
report_to_overling({type:'disrupt', reason})
|
||||
} else
|
||||
report_to_overling({type:'stop'})
|
||||
@@ -241,6 +235,9 @@ var runtime_env = {
|
||||
sequence: sequence
|
||||
}
|
||||
|
||||
// Make runtime functions available to modules loaded via use_core
|
||||
arrfor(array(runtime_env), function(k) { core_extras[k] = runtime_env[k] })
|
||||
|
||||
// Pass to os for shop to access
|
||||
os.runtime_env = runtime_env
|
||||
|
||||
@@ -300,8 +297,8 @@ $_.time_limit = function(requestor, seconds)
|
||||
callback(val, reason)
|
||||
}, value)
|
||||
} disruption {
|
||||
cancel(Error('requestor failed'))
|
||||
callback(null, Error('requestor failed'))
|
||||
cancel('requestor failed')
|
||||
callback(null, 'requestor failed')
|
||||
}
|
||||
do_request()
|
||||
|
||||
@@ -821,6 +818,7 @@ function enet_check()
|
||||
actor_mod.setname(_cell.args.program)
|
||||
|
||||
var prog = _cell.args.program
|
||||
if (ends_with(prog, '.ce')) prog = text(prog, 0, -3)
|
||||
|
||||
var package = use_core('package')
|
||||
|
||||
@@ -863,7 +861,11 @@ $_.clock(_ => {
|
||||
}
|
||||
|
||||
var pkg = file_info ? file_info.package : null
|
||||
env.use = function(path) { return shop.use(path, pkg) }
|
||||
env.use = function(path) {
|
||||
var ck = 'core/' + path
|
||||
if (use_cache[ck]) return use_cache[ck]
|
||||
return shop.use(path, pkg)
|
||||
}
|
||||
env.args = _cell.args.arg
|
||||
env.log = log
|
||||
|
||||
|
||||
Binary file not shown.
111
internal/shop.cm
111
internal/shop.cm
@@ -80,12 +80,12 @@ function get_packages_dir() {
|
||||
}
|
||||
|
||||
// Get the core directory (in the global shop)
|
||||
var core_package = 'core'
|
||||
|
||||
Shop.get_core_dir = function() {
|
||||
return get_packages_dir() + '/' + core_package
|
||||
}
|
||||
|
||||
var core_package = 'core'
|
||||
|
||||
// Get the links file path (in the global shop)
|
||||
function get_links_path() {
|
||||
return global_shop_path + '/link.toml'
|
||||
@@ -400,98 +400,54 @@ Shop.get_script_capabilities = function(path) {
|
||||
return Shop.script_inject_for(file_info)
|
||||
}
|
||||
|
||||
// Build the env object for a module, with runtime fns and $-prefixed capabilities.
|
||||
// Matches engine.cm's approach: env properties become free variables in the module.
|
||||
function inject_env(inject) {
|
||||
// Start with runtime functions from engine
|
||||
var env = {}
|
||||
var rt = my$_.os ? my$_.os.runtime_env : null
|
||||
if (rt) {
|
||||
arrfor(array(rt), function(k) { env[k] = rt[k] })
|
||||
}
|
||||
|
||||
// Add capability injections
|
||||
// Add capability injections with $ prefix
|
||||
var i = 0
|
||||
var inj = null
|
||||
var key = null
|
||||
for (i = 0; i < length(inject); i++) {
|
||||
inj = inject[i]
|
||||
key = trim(inj, '$')
|
||||
if (key == 'fd') env[key] = fd
|
||||
else env[key] = my$_[key]
|
||||
key = inj
|
||||
if (key && key[0] == '$') key = text(key, 1)
|
||||
if (key == 'fd') env['$fd'] = fd
|
||||
else env['$' + key] = my$_[key]
|
||||
}
|
||||
return env
|
||||
}
|
||||
|
||||
function inject_bindings_code(inject) {
|
||||
var lines = []
|
||||
|
||||
// Runtime function bindings
|
||||
var runtime_fns = ['logical', 'some', 'every', 'starts_with', 'ends_with',
|
||||
'actor', 'is_actor', 'log', 'send',
|
||||
'fallback', 'parallel', 'race', 'sequence']
|
||||
var i = 0
|
||||
var fn = null
|
||||
var inj = null
|
||||
var key = null
|
||||
for (i = 0; i < length(runtime_fns); i++) {
|
||||
fn = runtime_fns[i]
|
||||
push(lines, `var ${fn} = env["${fn}"];`)
|
||||
}
|
||||
|
||||
// Capability bindings ($delay, $start, etc.)
|
||||
for (i = 0; i < length(inject); i++) {
|
||||
inj = inject[i]
|
||||
key = trim(inj, '$')
|
||||
push(lines, `var $${key} = env["${key}"];`)
|
||||
}
|
||||
return text(lines, '\n')
|
||||
}
|
||||
|
||||
// Build the use function for a specific package context
|
||||
function make_use_fn_code(pkg_arg) {
|
||||
return `function(path) { return globalThis.use(path, ${pkg_arg}); }`
|
||||
}
|
||||
|
||||
// for script forms, path is the canonical path of the module
|
||||
var script_form = function(path, script, pkg, inject) {
|
||||
var pkg_arg = pkg ? `'${pkg}'` : 'null'
|
||||
var binds = inject_bindings_code(inject)
|
||||
|
||||
var fn = `(function setup_module(args, use, env){
|
||||
def arg = args;
|
||||
def PACKAGE = ${pkg_arg};
|
||||
${binds}
|
||||
${script}
|
||||
})`
|
||||
return fn
|
||||
}
|
||||
|
||||
// Resolve module function, hashing it in the process
|
||||
// path is the exact path to the script file
|
||||
// Compile a module and return its bytecode blob.
|
||||
// The bytecode is cached on disk by content hash.
|
||||
function resolve_mod_fn(path, pkg) {
|
||||
if (!fd.is_file(path)) { print(`path ${path} is not a file`); disrupt }
|
||||
|
||||
var file_info = Shop.file_info(path)
|
||||
var file_pkg = file_info.package
|
||||
var inject = Shop.script_inject_for(file_info)
|
||||
var content = text(fd.slurp(path))
|
||||
var script = script_form(path, content, file_pkg, inject)
|
||||
|
||||
// Check cache for pre-compiled .mach blob
|
||||
var cached = pull_from_cache(stone(blob(script)))
|
||||
var cached = pull_from_cache(stone(blob(content)))
|
||||
var ast = null
|
||||
var ast_json = null
|
||||
var compiled = null
|
||||
if (cached) {
|
||||
return mach_load(cached)
|
||||
return cached
|
||||
}
|
||||
|
||||
// Compile via new pipeline
|
||||
var ast = analyze(script, path)
|
||||
var ast_json = shop_json.encode(ast)
|
||||
ast = analyze(content, path)
|
||||
ast_json = shop_json.encode(ast)
|
||||
|
||||
// Cache compiled binary
|
||||
var compiled = mach_compile_ast(path, ast_json)
|
||||
put_into_cache(stone(blob(script)), compiled)
|
||||
compiled = mach_compile_ast(path, ast_json)
|
||||
put_into_cache(stone(blob(content)), compiled)
|
||||
|
||||
// Evaluate to get the function object
|
||||
return mach_eval_ast(path, ast_json)
|
||||
return compiled
|
||||
}
|
||||
|
||||
// given a path and a package context
|
||||
@@ -854,29 +810,26 @@ function execute_module(info)
|
||||
var mod_resolve = info.mod_resolve
|
||||
|
||||
var used = null
|
||||
var context = null
|
||||
var file_info = null
|
||||
var inject = null
|
||||
var env = null
|
||||
var pkg = null
|
||||
var use_fn = null
|
||||
|
||||
if (mod_resolve.scope < 900) {
|
||||
context = null
|
||||
if (c_resolve.scope < 900) {
|
||||
context = call_c_module(c_resolve)
|
||||
}
|
||||
|
||||
// Get file info to determine inject list
|
||||
// Build env with runtime fns, capabilities, and use function
|
||||
file_info = Shop.file_info(mod_resolve.path)
|
||||
inject = Shop.script_inject_for(file_info)
|
||||
env = inject_env(inject)
|
||||
pkg = file_info.package
|
||||
use_fn = make_use_fn(pkg)
|
||||
env.use = make_use_fn(pkg)
|
||||
|
||||
// Call with signature: setup_module(args, use, env)
|
||||
// args is null for module loading
|
||||
used = call(mod_resolve.symbol, context, [null, use_fn, env])
|
||||
// Add C module as native context if available
|
||||
if (c_resolve.scope < 900) {
|
||||
env.native = call_c_module(c_resolve)
|
||||
}
|
||||
|
||||
// Load compiled bytecode with env
|
||||
used = mach_load(mod_resolve.symbol, env)
|
||||
} else if (c_resolve.scope < 900) {
|
||||
// C only
|
||||
used = call_c_module(c_resolve)
|
||||
@@ -884,12 +837,8 @@ function execute_module(info)
|
||||
print(`Module ${info.path} could not be found`); disrupt
|
||||
}
|
||||
|
||||
// if (is_function(used))
|
||||
// throw Error('C module loader returned a function; did you forget to call it?')
|
||||
|
||||
if (!used) { print(`Module ${info} returned null`); disrupt }
|
||||
|
||||
// stone(used)
|
||||
return used
|
||||
}
|
||||
|
||||
|
||||
2
parse.cm
2
parse.cm
@@ -1661,6 +1661,8 @@ var parse = function(tokens, src, filename, tokenizer) {
|
||||
operand.level = -1
|
||||
}
|
||||
}
|
||||
} else if (operand != null) {
|
||||
sem_check_assign_target(scope, operand)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
BIN
parse.mach
BIN
parse.mach
Binary file not shown.
@@ -44,9 +44,10 @@ function fallback(requestor_array) {
|
||||
var cancelled = false
|
||||
|
||||
function cancel(reason) {
|
||||
var _c = null
|
||||
cancelled = true
|
||||
if (current_cancel) {
|
||||
var _c = function() { current_cancel(reason) } disruption {}
|
||||
_c = function() { current_cancel(reason) } disruption {}
|
||||
_c()
|
||||
current_cancel = null
|
||||
}
|
||||
@@ -293,9 +294,10 @@ function sequence(requestor_array) {
|
||||
var cancelled = false
|
||||
|
||||
function cancel(reason) {
|
||||
var _c = null
|
||||
cancelled = true
|
||||
if (current_cancel) {
|
||||
var _c = function() { current_cancel(reason) } disruption {}
|
||||
_c = function() { current_cancel(reason) } disruption {}
|
||||
_c()
|
||||
current_cancel = null
|
||||
}
|
||||
|
||||
@@ -462,7 +462,7 @@ int cell_init(int argc, char **argv)
|
||||
if (scheduler_actor_count() > 0) {
|
||||
actor_loop();
|
||||
exit_handler();
|
||||
return exit_code;
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* No actors spawned — clean up CLI context */
|
||||
|
||||
144
source/mach.c
144
source/mach.c
@@ -608,6 +608,11 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
|
||||
int ki = mach_cpool_add_str(cs, prop_name);
|
||||
|
||||
/* If ki overflows 8-bit C field, load key into R(base+1) register */
|
||||
if (ki >= 0xFF) {
|
||||
mach_emit(cs, MACH_ABx(MACH_LOADK, base + 1, ki));
|
||||
}
|
||||
|
||||
/* Compile args into R(base+2)..R(base+1+nargs) */
|
||||
for (int i = 0; i < nargs; i++) {
|
||||
int arg_reg = mach_reserve_reg(cs);
|
||||
@@ -617,7 +622,7 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, arg_reg, r, 0));
|
||||
}
|
||||
|
||||
mach_emit(cs, MACH_ABC(MACH_CALLMETHOD, base, nargs, ki));
|
||||
mach_emit(cs, MACH_ABC(MACH_CALLMETHOD, base, nargs, ki >= 0xFF ? 0xFF : ki));
|
||||
mach_free_reg_to(cs, save_freereg);
|
||||
if (dest >= 0 && dest != base)
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, base, 0));
|
||||
@@ -843,19 +848,95 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
int slot = mach_find_var(cs, name);
|
||||
if (slot >= 0) {
|
||||
if (is_postfix) {
|
||||
/* Return old value, then increment */
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, slot, 0));
|
||||
mach_emit(cs, MACH_ABC(inc_op, slot, slot, 0));
|
||||
} else {
|
||||
/* Increment, then return new value */
|
||||
mach_emit(cs, MACH_ABC(inc_op, slot, slot, 0));
|
||||
if (dest != slot)
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, slot, 0));
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
} else if (level > 0 && name) {
|
||||
/* Closure variable */
|
||||
int save = cs->freereg;
|
||||
MachCompState *target = cs;
|
||||
for (int i = 0; i < level; i++) target = target->parent;
|
||||
int slot = mach_find_var(target, name);
|
||||
int val_r = mach_reserve_reg(cs);
|
||||
mach_emit(cs, MACH_ABC(MACH_GETUP, val_r, level, slot));
|
||||
if (is_postfix)
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, val_r, 0));
|
||||
mach_emit(cs, MACH_ABC(inc_op, val_r, val_r, 0));
|
||||
if (!is_postfix)
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, val_r, 0));
|
||||
mach_emit(cs, MACH_ABC(MACH_SETUP, val_r, level, slot));
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
/* Property access: obj.prop++ */
|
||||
if (op_kind && strcmp(op_kind, ".") == 0) {
|
||||
int save = cs->freereg;
|
||||
cJSON *obj_expr = cJSON_GetObjectItemCaseSensitive(operand, "expression");
|
||||
if (!obj_expr) obj_expr = cJSON_GetObjectItemCaseSensitive(operand, "left");
|
||||
cJSON *prop = cJSON_GetObjectItemCaseSensitive(operand, "name");
|
||||
if (!prop) prop = cJSON_GetObjectItemCaseSensitive(operand, "right");
|
||||
const char *prop_name = NULL;
|
||||
if (cJSON_IsString(prop)) prop_name = cJSON_GetStringValue(prop);
|
||||
else if (prop) prop_name = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(prop, "value"));
|
||||
if (!prop_name && prop) prop_name = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(prop, "name"));
|
||||
if (!prop_name) prop_name = cJSON_GetStringValue(cJSON_GetObjectItemCaseSensitive(operand, "value"));
|
||||
if (prop_name) {
|
||||
int obj_r = mach_compile_expr(cs, obj_expr, -1);
|
||||
if (cs->freereg <= obj_r) cs->freereg = obj_r + 1;
|
||||
int ki = mach_cpool_add_str(cs, prop_name);
|
||||
int val_r = mach_reserve_reg(cs);
|
||||
if (ki < 256) {
|
||||
mach_emit(cs, MACH_ABC(MACH_GETFIELD, val_r, obj_r, ki));
|
||||
} else {
|
||||
int kr = mach_reserve_reg(cs);
|
||||
mach_emit(cs, MACH_ABx(MACH_LOADK, kr, ki));
|
||||
mach_emit(cs, MACH_ABC(MACH_GETINDEX, val_r, obj_r, kr));
|
||||
}
|
||||
if (is_postfix)
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, val_r, 0));
|
||||
mach_emit(cs, MACH_ABC(inc_op, val_r, val_r, 0));
|
||||
if (!is_postfix)
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, val_r, 0));
|
||||
if (ki < 256) {
|
||||
mach_emit(cs, MACH_ABC(MACH_SETFIELD, obj_r, ki, val_r));
|
||||
} else {
|
||||
int kr = mach_reserve_reg(cs);
|
||||
mach_emit(cs, MACH_ABx(MACH_LOADK, kr, ki));
|
||||
mach_emit(cs, MACH_ABC(MACH_SETINDEX, obj_r, kr, val_r));
|
||||
}
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
}
|
||||
/* Computed property access: obj[idx]++ */
|
||||
if (op_kind && strcmp(op_kind, "[") == 0) {
|
||||
int save = cs->freereg;
|
||||
cJSON *obj_expr = cJSON_GetObjectItemCaseSensitive(operand, "expression");
|
||||
if (!obj_expr) obj_expr = cJSON_GetObjectItemCaseSensitive(operand, "left");
|
||||
cJSON *idx_expr = cJSON_GetObjectItemCaseSensitive(operand, "index");
|
||||
if (!idx_expr) idx_expr = cJSON_GetObjectItemCaseSensitive(operand, "right");
|
||||
int obj_r = mach_compile_expr(cs, obj_expr, -1);
|
||||
if (cs->freereg <= obj_r) cs->freereg = obj_r + 1;
|
||||
int idx_r = mach_compile_expr(cs, idx_expr, -1);
|
||||
if (cs->freereg <= idx_r) cs->freereg = idx_r + 1;
|
||||
int val_r = mach_reserve_reg(cs);
|
||||
mach_emit(cs, MACH_ABC(MACH_GETINDEX, val_r, obj_r, idx_r));
|
||||
if (is_postfix)
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, val_r, 0));
|
||||
mach_emit(cs, MACH_ABC(inc_op, val_r, val_r, 0));
|
||||
if (!is_postfix)
|
||||
mach_emit(cs, MACH_ABC(MACH_MOVE, dest, val_r, 0));
|
||||
mach_emit(cs, MACH_ABC(MACH_SETINDEX, obj_r, idx_r, val_r));
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
}
|
||||
/* Fallback: just compile operand */
|
||||
return mach_compile_expr(cs, operand, dest);
|
||||
}
|
||||
@@ -999,7 +1080,13 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
int val_r = mach_compile_expr(cs, right, dest);
|
||||
if (prop_name) {
|
||||
int ki = mach_cpool_add_str(cs, prop_name);
|
||||
mach_emit(cs, MACH_ABC(MACH_SETFIELD, obj_r, ki, val_r));
|
||||
if (ki < 256) {
|
||||
mach_emit(cs, MACH_ABC(MACH_SETFIELD, obj_r, ki, val_r));
|
||||
} else {
|
||||
int kr = mach_reserve_reg(cs);
|
||||
mach_emit(cs, MACH_ABx(MACH_LOADK, kr, ki));
|
||||
mach_emit(cs, MACH_ABC(MACH_SETINDEX, obj_r, kr, val_r));
|
||||
}
|
||||
}
|
||||
mach_free_reg_to(cs, save);
|
||||
return val_r;
|
||||
@@ -1047,7 +1134,13 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
int obj_r = mach_compile_expr(cs, obj_expr, -1);
|
||||
if (prop_name) {
|
||||
int ki = mach_cpool_add_str(cs, prop_name);
|
||||
mach_emit(cs, MACH_ABC(MACH_GETFIELD, dest, obj_r, ki));
|
||||
if (ki < 256) {
|
||||
mach_emit(cs, MACH_ABC(MACH_GETFIELD, dest, obj_r, ki));
|
||||
} else {
|
||||
int kr = mach_reserve_reg(cs);
|
||||
mach_emit(cs, MACH_ABx(MACH_LOADK, kr, ki));
|
||||
mach_emit(cs, MACH_ABC(MACH_GETINDEX, dest, obj_r, kr));
|
||||
}
|
||||
}
|
||||
mach_free_reg_to(cs, save);
|
||||
return dest;
|
||||
@@ -1091,7 +1184,13 @@ static int mach_compile_expr(MachCompState *cs, cJSON *node, int dest) {
|
||||
int save = cs->freereg;
|
||||
int vr = mach_compile_expr(cs, val_node, -1);
|
||||
int ki = mach_cpool_add_str(cs, key);
|
||||
mach_emit(cs, MACH_ABC(MACH_SETFIELD, dest, ki, vr));
|
||||
if (ki < 256) {
|
||||
mach_emit(cs, MACH_ABC(MACH_SETFIELD, dest, ki, vr));
|
||||
} else {
|
||||
int kr = mach_reserve_reg(cs);
|
||||
mach_emit(cs, MACH_ABx(MACH_LOADK, kr, ki));
|
||||
mach_emit(cs, MACH_ABC(MACH_SETINDEX, dest, kr, vr));
|
||||
}
|
||||
mach_free_reg_to(cs, save);
|
||||
}
|
||||
}
|
||||
@@ -2552,7 +2651,7 @@ static JSValue reg_vm_binop(JSContext *ctx, int op, JSValue a, JSValue b) {
|
||||
}
|
||||
|
||||
/* Type mismatch — disrupt */
|
||||
return JS_EXCEPTION;
|
||||
return JS_ThrowTypeError(ctx, "type mismatch in binary operation");
|
||||
}
|
||||
|
||||
/* Check for interrupt */
|
||||
@@ -3021,6 +3120,8 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
JSValue func_val = frame->slots[base];
|
||||
|
||||
if (!JS_IsFunction(func_val)) {
|
||||
JS_ThrowTypeError(ctx, "not a function");
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
goto disrupt;
|
||||
}
|
||||
|
||||
@@ -3123,13 +3224,18 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
goto disrupt;
|
||||
} else {
|
||||
/* Record method call: get property, call with this=obj */
|
||||
if (JS_IsNull(frame->slots[base])) {
|
||||
JS_ThrowTypeError(ctx, "cannot read properties of null");
|
||||
JS_PopGCRef(ctx, &key_ref);
|
||||
goto disrupt;
|
||||
}
|
||||
JSValue method = JS_GetProperty(ctx, frame->slots[base], key_ref.val);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (JS_IsException(method)) { JS_PopGCRef(ctx, &key_ref); goto disrupt; }
|
||||
if (!JS_IsFunction(method)) {
|
||||
frame->slots[base] = JS_NULL;
|
||||
JS_ThrowTypeError(ctx, "not a function");
|
||||
JS_PopGCRef(ctx, &key_ref);
|
||||
break;
|
||||
goto disrupt;
|
||||
}
|
||||
JSFunction *fn = JS_VALUE_GET_FUNCTION(method);
|
||||
if (fn->kind == JS_FUNC_KIND_C) {
|
||||
@@ -3263,7 +3369,11 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
/* push R(B) onto array R(A) */
|
||||
JSValue arr = frame->slots[a];
|
||||
JSValue val = frame->slots[b];
|
||||
if (!JS_IsArray(arr)) goto disrupt;
|
||||
if (!JS_IsArray(arr)) {
|
||||
JS_ThrowTypeError(ctx, "cannot push to non-array");
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
goto disrupt;
|
||||
}
|
||||
JSGCRef arr_gc;
|
||||
JS_PushGCRef(ctx, &arr_gc);
|
||||
arr_gc.val = arr;
|
||||
@@ -3278,7 +3388,11 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
case MACH_POP: {
|
||||
/* R(A) = pop last element from array R(B) */
|
||||
JSValue arr = frame->slots[b];
|
||||
if (!JS_IsArray(arr)) goto disrupt;
|
||||
if (!JS_IsArray(arr)) {
|
||||
JS_ThrowTypeError(ctx, "cannot pop from non-array");
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
goto disrupt;
|
||||
}
|
||||
JSValue val = JS_ArrayPop(ctx, arr);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
if (JS_IsException(val)) goto disrupt;
|
||||
@@ -3353,7 +3467,13 @@ JSValue JS_CallRegisterVM(JSContext *ctx, JSCodeRegister *code,
|
||||
break;
|
||||
}
|
||||
if (JS_IsNull(frame->caller)) {
|
||||
fprintf(stderr, "unhandled disruption\n");
|
||||
if (!JS_HasException(ctx)) {
|
||||
/* Bare disrupt with no error message — provide location */
|
||||
const char *fn_name = code->name_cstr ? code->name_cstr : "<anonymous>";
|
||||
fprintf(stderr, "unhandled disruption in %s\n", fn_name);
|
||||
} else {
|
||||
fprintf(stderr, "unhandled disruption\n");
|
||||
}
|
||||
result = JS_Throw(ctx, JS_NULL);
|
||||
frame = (JSFrameRegister *)JS_VALUE_GET_PTR(frame_ref.val);
|
||||
goto done;
|
||||
|
||||
@@ -8255,12 +8255,17 @@ static JSValue js_cell_text_format (JSContext *ctx, JSValue this_val, int argc,
|
||||
if (!result) { FMT_CLEANUP(); return JS_EXCEPTION; }
|
||||
res_ref.val = JS_MKPTR (result);
|
||||
} else {
|
||||
JSValue orig = js_sub_string_val (ctx, text_ref.val, brace_start, brace_end + 1);
|
||||
if (JS_IsException (orig)) { FMT_CLEANUP(); return JS_EXCEPTION; }
|
||||
/* No substitution — treat the '{' as a literal character and rescan
|
||||
from brace_start + 1 so that real placeholders like {0} inside
|
||||
the skipped range are still found. */
|
||||
JSValue ch = js_sub_string_val (ctx, text_ref.val, brace_start, brace_start + 1);
|
||||
if (JS_IsException (ch)) { FMT_CLEANUP(); return JS_EXCEPTION; }
|
||||
result = (JSText *)chase (res_ref.val);
|
||||
result = pretext_concat_value (ctx, result, orig);
|
||||
result = pretext_concat_value (ctx, result, ch);
|
||||
if (!result) { FMT_CLEANUP(); return JS_EXCEPTION; }
|
||||
res_ref.val = JS_MKPTR (result);
|
||||
pos = brace_start + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
pos = brace_end + 1;
|
||||
@@ -9923,7 +9928,7 @@ static JSValue js_blob_constructor (JSContext *ctx, JSValue this_val, int argc,
|
||||
}
|
||||
}
|
||||
/* blob(blob, from, to) - copy from another blob */
|
||||
else if (argc >= 1 && JS_IsObject (argv[0])) {
|
||||
else if (argc >= 1 && JS_IsObject (argv[0]) && !JS_IsText (argv[0])) {
|
||||
blob *src = js_get_blob (ctx, argv[0]);
|
||||
if (!src)
|
||||
return JS_ThrowTypeError (ctx,
|
||||
@@ -9941,9 +9946,7 @@ static JSValue js_blob_constructor (JSContext *ctx, JSValue this_val, int argc,
|
||||
bd = blob_new_from_blob (src, (size_t)from, (size_t)to);
|
||||
}
|
||||
/* blob(text) - create blob from UTF-8 string */
|
||||
else if (argc == 1
|
||||
&& (JS_VALUE_GET_TAG (argv[0]) == JS_TAG_STRING
|
||||
|| JS_VALUE_GET_TAG (argv[0]) == JS_TAG_STRING_IMM)) {
|
||||
else if (argc == 1 && JS_IsText (argv[0])) {
|
||||
const char *str = JS_ToCString (ctx, argv[0]);
|
||||
if (!str) return JS_EXCEPTION;
|
||||
size_t len = strlen (str);
|
||||
|
||||
@@ -304,6 +304,7 @@ void actor_free(cell_rt *actor)
|
||||
|
||||
int actor_count = lockless_shlen(actors);
|
||||
if (actor_count == 0) {
|
||||
fprintf(stderr, "all actors are dead\n");
|
||||
pthread_mutex_lock(&engine.lock);
|
||||
engine.shutting_down = 1;
|
||||
pthread_cond_broadcast(&engine.wake_cond);
|
||||
@@ -533,7 +534,7 @@ const char *register_actor(const char *id, cell_rt *actor, int mainthread, doubl
|
||||
actor->main_thread_only = mainthread;
|
||||
actor->id = strdup(id);
|
||||
actor->ar_secs = ar;
|
||||
int added = lockless_shput_unique(actors, id, actor);
|
||||
int added = lockless_shput_unique(actors, actor->id, actor);
|
||||
if (!added) {
|
||||
free(actor->id);
|
||||
return "Actor with given ID already exists.";
|
||||
@@ -591,20 +592,22 @@ void actor_turn(cell_rt *actor)
|
||||
arrdel(actor->letters, 0); // O(N) but we kept array as requested
|
||||
pthread_mutex_unlock(actor->msg_mutex);
|
||||
|
||||
if (l.type == LETTER_BLOB) {
|
||||
if (l.type == LETTER_BLOB) {
|
||||
// Create a JS blob from the C blob
|
||||
size_t size = blob_length(l.blob_data) / 8; // Convert bits to bytes
|
||||
JSValue arg = js_new_blob_stoned_copy(actor->context, (void*)blob_data(l.blob_data), size);
|
||||
blob_destroy(l.blob_data);
|
||||
result = JS_Call(actor->context, actor->message_handle_ref.val, JS_NULL, 1, &arg);
|
||||
uncaught_exception(actor->context, result);
|
||||
if (!uncaught_exception(actor->context, result))
|
||||
actor->disrupt = 1;
|
||||
JS_FreeValue(actor->context, arg);
|
||||
} else if (l.type == LETTER_CALLBACK) {
|
||||
result = JS_Call(actor->context, l.callback, JS_NULL, 0, NULL);
|
||||
uncaught_exception(actor->context, result);
|
||||
if (!uncaught_exception(actor->context, result))
|
||||
actor->disrupt = 1;
|
||||
JS_FreeValue(actor->context, l.callback);
|
||||
}
|
||||
|
||||
|
||||
if (actor->disrupt) goto ENDTURN;
|
||||
|
||||
ENDTURN:
|
||||
@@ -612,9 +615,17 @@ void actor_turn(cell_rt *actor)
|
||||
|
||||
if (actor->trace_hook)
|
||||
actor->trace_hook(actor->name, CELL_HOOK_EXIT);
|
||||
|
||||
|
||||
if (actor->disrupt) {
|
||||
/* Actor must die. Unlock before freeing so actor_free can
|
||||
lock/unlock/destroy the mutex without use-after-free. */
|
||||
pthread_mutex_unlock(actor->mutex);
|
||||
actor_free(actor);
|
||||
return;
|
||||
}
|
||||
|
||||
set_actor_state(actor);
|
||||
|
||||
|
||||
pthread_mutex_unlock(actor->mutex);
|
||||
}
|
||||
|
||||
|
||||
91
test.ce
91
test.ce
@@ -304,9 +304,12 @@ function run_tests(package_name, specific_test) {
|
||||
}
|
||||
|
||||
var _load_file = null
|
||||
var load_error = false
|
||||
var err_entry = null
|
||||
for (i = 0; i < length(test_files); i++) {
|
||||
f = test_files[i]
|
||||
mod_path = text(f, 0, -3) // remove .cm
|
||||
load_error = false
|
||||
|
||||
file_result = {
|
||||
name: f,
|
||||
@@ -328,14 +331,34 @@ function run_tests(package_name, specific_test) {
|
||||
var _test_error = null
|
||||
var end_time = null
|
||||
var _run_one = null
|
||||
var all_keys = null
|
||||
var fn_count = 0
|
||||
var null_count = 0
|
||||
var other_count = 0
|
||||
var first_null_key = null
|
||||
var first_other_key = null
|
||||
if (is_function(test_mod)) {
|
||||
push(tests, {name: 'main', fn: test_mod})
|
||||
} else if (is_object(test_mod)) {
|
||||
arrfor(array(test_mod), function(k) {
|
||||
all_keys = array(test_mod)
|
||||
log.console(` Found ${length(all_keys)} test entries`)
|
||||
arrfor(all_keys, function(k) {
|
||||
if (is_function(test_mod[k])) {
|
||||
fn_count = fn_count + 1
|
||||
push(tests, {name: k, fn: test_mod[k]})
|
||||
} else if (is_null(test_mod[k])) {
|
||||
null_count = null_count + 1
|
||||
if (!first_null_key) first_null_key = k
|
||||
} else {
|
||||
other_count = other_count + 1
|
||||
if (!first_other_key) first_other_key = k
|
||||
}
|
||||
})
|
||||
log.console(` functions=${fn_count} nulls=${null_count} other=${other_count}`)
|
||||
if (first_other_key) {
|
||||
log.console(` first other key: ${first_other_key}`)
|
||||
log.console(` is_number=${is_number(test_mod[first_other_key])} is_text=${is_text(test_mod[first_other_key])} is_logical=${is_logical(test_mod[first_other_key])} is_object=${is_object(test_mod[first_other_key])}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (length(tests) > 0) {
|
||||
@@ -355,17 +378,15 @@ function run_tests(package_name, specific_test) {
|
||||
var ret = t.fn()
|
||||
|
||||
if (is_text(ret)) {
|
||||
_test_error = Error(ret)
|
||||
disrupt
|
||||
} else if (ret && (is_text(ret.message) || is_proto(ret, Error))) {
|
||||
_test_error = ret
|
||||
disrupt
|
||||
} else if (ret && is_text(ret.message)) {
|
||||
_test_error = ret.message
|
||||
disrupt
|
||||
}
|
||||
|
||||
test_entry.status = "passed"
|
||||
log.console(` PASS ${t.name}`)
|
||||
pkg_result.passed++
|
||||
file_result.passed++
|
||||
} disruption {
|
||||
var e = _test_error
|
||||
test_entry.status = "failed"
|
||||
@@ -383,16 +404,22 @@ function run_tests(package_name, specific_test) {
|
||||
if (test_entry.error.stack) {
|
||||
log.console(` ${text(array(test_entry.error.stack, '\n'), '\n ')}`)
|
||||
}
|
||||
|
||||
pkg_result.failed++
|
||||
file_result.failed++
|
||||
}
|
||||
_run_one()
|
||||
end_time = time.number()
|
||||
test_entry.duration_ns = round((end_time - start_time) * 1000000000)
|
||||
|
||||
// Update counters at _load_file level (not inside _run_one)
|
||||
if (test_entry.status == "passed") {
|
||||
pkg_result.passed = pkg_result.passed + 1
|
||||
file_result.passed = file_result.passed + 1
|
||||
} else {
|
||||
pkg_result.failed = pkg_result.failed + 1
|
||||
file_result.failed = file_result.failed + 1
|
||||
}
|
||||
|
||||
push(file_result.tests, test_entry)
|
||||
pkg_result.total++
|
||||
pkg_result.total = pkg_result.total + 1
|
||||
if (gc_after_each_test) {
|
||||
dbg.gc()
|
||||
}
|
||||
@@ -400,23 +427,15 @@ function run_tests(package_name, specific_test) {
|
||||
}
|
||||
|
||||
} disruption {
|
||||
var test_entry = {
|
||||
package: pkg_result.package,
|
||||
test: "load_module",
|
||||
status: "failed",
|
||||
duration_ns: 0,
|
||||
error: { message: `Error loading module` }
|
||||
}
|
||||
log.console(` Error loading ${f}`)
|
||||
push(file_result.tests, test_entry)
|
||||
pkg_result.failed++
|
||||
file_result.failed++
|
||||
pkg_result.total++
|
||||
if (gc_after_each_test) {
|
||||
dbg.gc()
|
||||
}
|
||||
load_error = true
|
||||
}
|
||||
_load_file()
|
||||
if (load_error) {
|
||||
log.console(" Error loading " + f)
|
||||
pkg_result.failed = pkg_result.failed + 1
|
||||
file_result.failed = file_result.failed + 1
|
||||
pkg_result.total = pkg_result.total + 1
|
||||
}
|
||||
push(pkg_result.files, file_result)
|
||||
}
|
||||
return pkg_result
|
||||
@@ -596,22 +615,22 @@ function finalize_results() {
|
||||
}
|
||||
|
||||
push(file_result.tests, r)
|
||||
pkg_result.total++
|
||||
pkg_result.total = pkg_result.total + 1
|
||||
if (r.status == "passed") {
|
||||
pkg_result.passed++
|
||||
file_result.passed++
|
||||
pkg_result.passed = pkg_result.passed + 1
|
||||
file_result.passed = file_result.passed + 1
|
||||
} else {
|
||||
pkg_result.failed++
|
||||
file_result.failed++
|
||||
pkg_result.failed = pkg_result.failed + 1
|
||||
file_result.failed = file_result.failed + 1
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate totals
|
||||
var totals = { total: 0, passed: 0, failed: 0 }
|
||||
for (i = 0; i < length(all_results); i++) {
|
||||
totals.total += all_results[i].total
|
||||
totals.passed += all_results[i].passed
|
||||
totals.failed += all_results[i].failed
|
||||
totals.total = totals.total + all_results[i].total
|
||||
totals.passed = totals.passed + all_results[i].passed
|
||||
totals.failed = totals.failed + all_results[i].failed
|
||||
}
|
||||
|
||||
log.console(`----------------------------------------`)
|
||||
@@ -626,9 +645,9 @@ var totals = null
|
||||
if (length(all_actor_tests) == 0) {
|
||||
totals = { total: 0, passed: 0, failed: 0 }
|
||||
for (i = 0; i < length(all_results); i++) {
|
||||
totals.total += all_results[i].total
|
||||
totals.passed += all_results[i].passed
|
||||
totals.failed += all_results[i].failed
|
||||
totals.total = totals.total + all_results[i].total
|
||||
totals.passed = totals.passed + all_results[i].passed
|
||||
totals.failed = totals.failed + all_results[i].failed
|
||||
}
|
||||
|
||||
log.console(`----------------------------------------`)
|
||||
|
||||
2012
tests/suite.cm
2012
tests/suite.cm
File diff suppressed because it is too large
Load Diff
2
time.cm
2
time.cm
@@ -1,5 +1,5 @@
|
||||
// epoch = 0000-01-01 00:00:00 +0000
|
||||
var time = this
|
||||
var time = native
|
||||
|
||||
var now = time.now
|
||||
var computer_zone = time.computer_zone
|
||||
|
||||
683
vm_suite.ce
683
vm_suite.ce
@@ -738,6 +738,95 @@ run("disruption re-raise", function() {
|
||||
if (!outer_caught) fail("disruption re-raise failed")
|
||||
})
|
||||
|
||||
run("disruption handler reads outer vars", function() {
|
||||
var msg = "hello"
|
||||
var result = null
|
||||
var fn = function() {
|
||||
disrupt
|
||||
} disruption {
|
||||
result = msg
|
||||
}
|
||||
fn()
|
||||
if (result != "hello") fail("handler could not read outer var")
|
||||
})
|
||||
|
||||
run("disruption handler modifies outer vars", function() {
|
||||
var count = 0
|
||||
var name = "before"
|
||||
var fn = function() {
|
||||
count = count + 1
|
||||
disrupt
|
||||
} disruption {
|
||||
count = count + 10
|
||||
name = "after"
|
||||
}
|
||||
fn()
|
||||
if (count != 11) fail("expected 11 got " + text(count))
|
||||
if (name != "after") fail("expected 'after' got " + name)
|
||||
})
|
||||
|
||||
run("disruption handler reads function locals", function() {
|
||||
var result = null
|
||||
var fn = function() {
|
||||
var local_val = 42
|
||||
var inner = function() {
|
||||
disrupt
|
||||
} disruption {
|
||||
result = local_val
|
||||
}
|
||||
inner()
|
||||
}
|
||||
fn()
|
||||
if (result != 42) fail("handler could not read local, got " + text(result))
|
||||
})
|
||||
|
||||
run("disruption handler with closure", function() {
|
||||
var results = []
|
||||
var make_fn = function(tag) {
|
||||
return function() {
|
||||
disrupt
|
||||
} disruption {
|
||||
results[] = tag
|
||||
}
|
||||
}
|
||||
var fn_a = make_fn("a")
|
||||
var fn_b = make_fn("b")
|
||||
fn_a()
|
||||
fn_b()
|
||||
if (length(results) != 2) fail("expected 2 results")
|
||||
if (results[0] != "a") fail("first closure tag wrong")
|
||||
if (results[1] != "b") fail("second closure tag wrong")
|
||||
})
|
||||
|
||||
run("disruption handler modifies loop state", function() {
|
||||
var total = 0
|
||||
var i = 0
|
||||
var fn = null
|
||||
while (i < 3) {
|
||||
fn = function() {
|
||||
disrupt
|
||||
} disruption {
|
||||
total = total + i
|
||||
}
|
||||
fn()
|
||||
i = i + 1
|
||||
}
|
||||
if (total != 3) fail("expected 3 got " + text(total))
|
||||
})
|
||||
|
||||
run("disruption handler accesses object from outer scope", function() {
|
||||
var obj = {x: 1, y: 2}
|
||||
var fn = function() {
|
||||
obj.x = 10
|
||||
disrupt
|
||||
} disruption {
|
||||
obj.y = 20
|
||||
}
|
||||
fn()
|
||||
if (obj.x != 10) fail("body mutation lost, x=" + text(obj.x))
|
||||
if (obj.y != 20) fail("handler mutation lost, y=" + text(obj.y))
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// TYPE CHECKING WITH is_* FUNCTIONS
|
||||
// ============================================================================
|
||||
@@ -1182,6 +1271,141 @@ run("prefix decrement on array element", function() {
|
||||
if (arr[0] != 9) fail("side effect")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// POSTFIX INCREMENT/DECREMENT ON PROPERTIES (Bug: never worked)
|
||||
// ============================================================================
|
||||
|
||||
run("postfix increment on property", function() {
|
||||
var obj = {x: 5}
|
||||
obj.x++
|
||||
assert_eq(obj.x, 6, "obj.x should be 6 after obj.x++")
|
||||
})
|
||||
|
||||
run("postfix decrement on property", function() {
|
||||
var obj = {x: 5}
|
||||
obj.x--
|
||||
assert_eq(obj.x, 4, "obj.x should be 4 after obj.x--")
|
||||
})
|
||||
|
||||
run("postfix increment on property return value", function() {
|
||||
var obj = {x: 5}
|
||||
var y = obj.x++
|
||||
assert_eq(y, 5, "return value should be old value")
|
||||
assert_eq(obj.x, 6, "property should be incremented")
|
||||
})
|
||||
|
||||
run("postfix decrement on property return value", function() {
|
||||
var obj = {x: 5}
|
||||
var y = obj.x--
|
||||
assert_eq(y, 5, "return value should be old value")
|
||||
assert_eq(obj.x, 4, "property should be decremented")
|
||||
})
|
||||
|
||||
run("postfix increment on array element", function() {
|
||||
var arr = [10, 20, 30]
|
||||
arr[1]++
|
||||
assert_eq(arr[1], 21, "arr[1] should be 21 after arr[1]++")
|
||||
})
|
||||
|
||||
run("postfix decrement on array element", function() {
|
||||
var arr = [10, 20, 30]
|
||||
arr[1]--
|
||||
assert_eq(arr[1], 19, "arr[1] should be 19 after arr[1]--")
|
||||
})
|
||||
|
||||
run("postfix increment on array element return value", function() {
|
||||
var arr = [10]
|
||||
var y = arr[0]++
|
||||
assert_eq(y, 10, "return value should be old value")
|
||||
assert_eq(arr[0], 11, "array element should be incremented")
|
||||
})
|
||||
|
||||
run("postfix increment on computed property", function() {
|
||||
var obj = {a: 10}
|
||||
var key = "a"
|
||||
obj[key]++
|
||||
assert_eq(obj.a, 11, "computed property should be incremented")
|
||||
})
|
||||
|
||||
run("postfix increment on nested property", function() {
|
||||
var obj = {inner: {val: 10}}
|
||||
obj.inner.val++
|
||||
assert_eq(obj.inner.val, 11, "nested property should be incremented")
|
||||
})
|
||||
|
||||
run("postfix increment property in loop", function() {
|
||||
var obj = {count: 0}
|
||||
var i = 0
|
||||
for (i = 0; i < 5; i++) {
|
||||
obj.count++
|
||||
}
|
||||
assert_eq(obj.count, 5, "property should be 5 after 5 increments")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// POSTFIX INCREMENT ON CLOSURE PROPERTIES (Original reported bug)
|
||||
// ============================================================================
|
||||
|
||||
run("postfix increment closure property", function() {
|
||||
var obj = {x: 0}
|
||||
var fn = function() {
|
||||
obj.x++
|
||||
}
|
||||
fn()
|
||||
assert_eq(obj.x, 1, "closure property should be incremented")
|
||||
})
|
||||
|
||||
run("postfix decrement closure property", function() {
|
||||
var obj = {x: 5}
|
||||
var fn = function() {
|
||||
obj.x--
|
||||
}
|
||||
fn()
|
||||
assert_eq(obj.x, 4, "closure property should be decremented")
|
||||
})
|
||||
|
||||
run("postfix increment closure counter pattern", function() {
|
||||
var counter = {passed: 0, failed: 0}
|
||||
var pass = function() { counter.passed++ }
|
||||
var fail_fn = function() { counter.failed++ }
|
||||
pass()
|
||||
pass()
|
||||
pass()
|
||||
fail_fn()
|
||||
assert_eq(counter.passed, 3, "passed count")
|
||||
assert_eq(counter.failed, 1, "failed count")
|
||||
})
|
||||
|
||||
run("postfix increment deep closure property", function() {
|
||||
var obj = {x: 0}
|
||||
var fn = function() {
|
||||
var inner = function() {
|
||||
obj.x++
|
||||
}
|
||||
inner()
|
||||
}
|
||||
fn()
|
||||
assert_eq(obj.x, 1, "deep closure property should be incremented")
|
||||
})
|
||||
|
||||
run("postfix increment closure array element", function() {
|
||||
var arr = [10]
|
||||
var fn = function() {
|
||||
arr[0]++
|
||||
}
|
||||
fn()
|
||||
assert_eq(arr[0], 11, "closure array element should be incremented")
|
||||
})
|
||||
|
||||
run("postfix increment on closure variable", function() {
|
||||
var x = 5
|
||||
var fn = function() {
|
||||
x++
|
||||
}
|
||||
fn()
|
||||
assert_eq(x, 6, "closure variable should be incremented by postfix ++")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// INCREMENT/DECREMENT IN LOOPS AND EXPRESSIONS
|
||||
// ============================================================================
|
||||
@@ -4262,6 +4486,465 @@ run("IIFE with arguments", function() {
|
||||
assert_eq(result, 30, "IIFE sum")
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// PATHOLOGICAL OBJECT LITERALS - Diagnose large object key/value limits
|
||||
// ============================================================================
|
||||
|
||||
// Test: object with 100 simple keys (number values)
|
||||
run("object literal 100 number keys", function() {
|
||||
var obj = {
|
||||
k000: 0, k001: 1, k002: 2, k003: 3, k004: 4, k005: 5, k006: 6, k007: 7, k008: 8, k009: 9,
|
||||
k010: 10, k011: 11, k012: 12, k013: 13, k014: 14, k015: 15, k016: 16, k017: 17, k018: 18, k019: 19,
|
||||
k020: 20, k021: 21, k022: 22, k023: 23, k024: 24, k025: 25, k026: 26, k027: 27, k028: 28, k029: 29,
|
||||
k030: 30, k031: 31, k032: 32, k033: 33, k034: 34, k035: 35, k036: 36, k037: 37, k038: 38, k039: 39,
|
||||
k040: 40, k041: 41, k042: 42, k043: 43, k044: 44, k045: 45, k046: 46, k047: 47, k048: 48, k049: 49,
|
||||
k050: 50, k051: 51, k052: 52, k053: 53, k054: 54, k055: 55, k056: 56, k057: 57, k058: 58, k059: 59,
|
||||
k060: 60, k061: 61, k062: 62, k063: 63, k064: 64, k065: 65, k066: 66, k067: 67, k068: 68, k069: 69,
|
||||
k070: 70, k071: 71, k072: 72, k073: 73, k074: 74, k075: 75, k076: 76, k077: 77, k078: 78, k079: 79,
|
||||
k080: 80, k081: 81, k082: 82, k083: 83, k084: 84, k085: 85, k086: 86, k087: 87, k088: 88, k089: 89,
|
||||
k090: 90, k091: 91, k092: 92, k093: 93, k094: 94, k095: 95, k096: 96, k097: 97, k098: 98, k099: 99
|
||||
}
|
||||
var keys = array(obj)
|
||||
assert_eq(length(keys), 100, "should have 100 keys")
|
||||
assert_eq(obj.k000, 0, "first key")
|
||||
assert_eq(obj.k099, 99, "last key")
|
||||
})
|
||||
|
||||
// Test: object with 200 simple keys (number values)
|
||||
run("object literal 200 number keys", function() {
|
||||
var obj = {
|
||||
k000: 0, k001: 1, k002: 2, k003: 3, k004: 4, k005: 5, k006: 6, k007: 7, k008: 8, k009: 9,
|
||||
k010: 10, k011: 11, k012: 12, k013: 13, k014: 14, k015: 15, k016: 16, k017: 17, k018: 18, k019: 19,
|
||||
k020: 20, k021: 21, k022: 22, k023: 23, k024: 24, k025: 25, k026: 26, k027: 27, k028: 28, k029: 29,
|
||||
k030: 30, k031: 31, k032: 32, k033: 33, k034: 34, k035: 35, k036: 36, k037: 37, k038: 38, k039: 39,
|
||||
k040: 40, k041: 41, k042: 42, k043: 43, k044: 44, k045: 45, k046: 46, k047: 47, k048: 48, k049: 49,
|
||||
k050: 50, k051: 51, k052: 52, k053: 53, k054: 54, k055: 55, k056: 56, k057: 57, k058: 58, k059: 59,
|
||||
k060: 60, k061: 61, k062: 62, k063: 63, k064: 64, k065: 65, k066: 66, k067: 67, k068: 68, k069: 69,
|
||||
k070: 70, k071: 71, k072: 72, k073: 73, k074: 74, k075: 75, k076: 76, k077: 77, k078: 78, k079: 79,
|
||||
k080: 80, k081: 81, k082: 82, k083: 83, k084: 84, k085: 85, k086: 86, k087: 87, k088: 88, k089: 89,
|
||||
k090: 90, k091: 91, k092: 92, k093: 93, k094: 94, k095: 95, k096: 96, k097: 97, k098: 98, k099: 99,
|
||||
k100: 100, k101: 101, k102: 102, k103: 103, k104: 104, k105: 105, k106: 106, k107: 107, k108: 108, k109: 109,
|
||||
k110: 110, k111: 111, k112: 112, k113: 113, k114: 114, k115: 115, k116: 116, k117: 117, k118: 118, k119: 119,
|
||||
k120: 120, k121: 121, k122: 122, k123: 123, k124: 124, k125: 125, k126: 126, k127: 127, k128: 128, k129: 129,
|
||||
k130: 130, k131: 131, k132: 132, k133: 133, k134: 134, k135: 135, k136: 136, k137: 137, k138: 138, k139: 139,
|
||||
k140: 140, k141: 141, k142: 142, k143: 143, k144: 144, k145: 145, k146: 146, k147: 147, k148: 148, k149: 149,
|
||||
k150: 150, k151: 151, k152: 152, k153: 153, k154: 154, k155: 155, k156: 156, k157: 157, k158: 158, k159: 159,
|
||||
k160: 160, k161: 161, k162: 162, k163: 163, k164: 164, k165: 165, k166: 166, k167: 167, k168: 168, k169: 169,
|
||||
k170: 170, k171: 171, k172: 172, k173: 173, k174: 174, k175: 175, k176: 176, k177: 177, k178: 178, k179: 179,
|
||||
k180: 180, k181: 181, k182: 182, k183: 183, k184: 184, k185: 185, k186: 186, k187: 187, k188: 188, k189: 189,
|
||||
k190: 190, k191: 191, k192: 192, k193: 193, k194: 194, k195: 195, k196: 196, k197: 197, k198: 198, k199: 199
|
||||
}
|
||||
var keys = array(obj)
|
||||
assert_eq(length(keys), 200, "should have 200 keys")
|
||||
assert_eq(obj.k000, 0, "first key")
|
||||
assert_eq(obj.k199, 199, "last key")
|
||||
})
|
||||
|
||||
// Test: object with 256 simple keys (number values) - exact boundary
|
||||
run("object literal 256 number keys", function() {
|
||||
var obj = {
|
||||
k000: 0, k001: 1, k002: 2, k003: 3, k004: 4, k005: 5, k006: 6, k007: 7, k008: 8, k009: 9,
|
||||
k010: 10, k011: 11, k012: 12, k013: 13, k014: 14, k015: 15, k016: 16, k017: 17, k018: 18, k019: 19,
|
||||
k020: 20, k021: 21, k022: 22, k023: 23, k024: 24, k025: 25, k026: 26, k027: 27, k028: 28, k029: 29,
|
||||
k030: 30, k031: 31, k032: 32, k033: 33, k034: 34, k035: 35, k036: 36, k037: 37, k038: 38, k039: 39,
|
||||
k040: 40, k041: 41, k042: 42, k043: 43, k044: 44, k045: 45, k046: 46, k047: 47, k048: 48, k049: 49,
|
||||
k050: 50, k051: 51, k052: 52, k053: 53, k054: 54, k055: 55, k056: 56, k057: 57, k058: 58, k059: 59,
|
||||
k060: 60, k061: 61, k062: 62, k063: 63, k064: 64, k065: 65, k066: 66, k067: 67, k068: 68, k069: 69,
|
||||
k070: 70, k071: 71, k072: 72, k073: 73, k074: 74, k075: 75, k076: 76, k077: 77, k078: 78, k079: 79,
|
||||
k080: 80, k081: 81, k082: 82, k083: 83, k084: 84, k085: 85, k086: 86, k087: 87, k088: 88, k089: 89,
|
||||
k090: 90, k091: 91, k092: 92, k093: 93, k094: 94, k095: 95, k096: 96, k097: 97, k098: 98, k099: 99,
|
||||
k100: 100, k101: 101, k102: 102, k103: 103, k104: 104, k105: 105, k106: 106, k107: 107, k108: 108, k109: 109,
|
||||
k110: 110, k111: 111, k112: 112, k113: 113, k114: 114, k115: 115, k116: 116, k117: 117, k118: 118, k119: 119,
|
||||
k120: 120, k121: 121, k122: 122, k123: 123, k124: 124, k125: 125, k126: 126, k127: 127, k128: 128, k129: 129,
|
||||
k130: 130, k131: 131, k132: 132, k133: 133, k134: 134, k135: 135, k136: 136, k137: 137, k138: 138, k139: 139,
|
||||
k140: 140, k141: 141, k142: 142, k143: 143, k144: 144, k145: 145, k146: 146, k147: 147, k148: 148, k149: 149,
|
||||
k150: 150, k151: 151, k152: 152, k153: 153, k154: 154, k155: 155, k156: 156, k157: 157, k158: 158, k159: 159,
|
||||
k160: 160, k161: 161, k162: 162, k163: 163, k164: 164, k165: 165, k166: 166, k167: 167, k168: 168, k169: 169,
|
||||
k170: 170, k171: 171, k172: 172, k173: 173, k174: 174, k175: 175, k176: 176, k177: 177, k178: 178, k179: 179,
|
||||
k180: 180, k181: 181, k182: 182, k183: 183, k184: 184, k185: 185, k186: 186, k187: 187, k188: 188, k189: 189,
|
||||
k190: 190, k191: 191, k192: 192, k193: 193, k194: 194, k195: 195, k196: 196, k197: 197, k198: 198, k199: 199,
|
||||
k200: 200, k201: 201, k202: 202, k203: 203, k204: 204, k205: 205, k206: 206, k207: 207, k208: 208, k209: 209,
|
||||
k210: 210, k211: 211, k212: 212, k213: 213, k214: 214, k215: 215, k216: 216, k217: 217, k218: 218, k219: 219,
|
||||
k220: 220, k221: 221, k222: 222, k223: 223, k224: 224, k225: 225, k226: 226, k227: 227, k228: 228, k229: 229,
|
||||
k230: 230, k231: 231, k232: 232, k233: 233, k234: 234, k235: 235, k236: 236, k237: 237, k238: 238, k239: 239,
|
||||
k240: 240, k241: 241, k242: 242, k243: 243, k244: 244, k245: 245, k246: 246, k247: 247, k248: 248, k249: 249,
|
||||
k250: 250, k251: 251, k252: 252, k253: 253, k254: 254, k255: 255
|
||||
}
|
||||
var keys = array(obj)
|
||||
assert_eq(length(keys), 256, "should have 256 keys")
|
||||
assert_eq(obj.k000, 0, "first key")
|
||||
assert_eq(obj.k255, 255, "last key")
|
||||
})
|
||||
|
||||
// Test: object with 257 keys - just past 256 boundary
|
||||
run("object literal 257 number keys", function() {
|
||||
var obj = {
|
||||
k000: 0, k001: 1, k002: 2, k003: 3, k004: 4, k005: 5, k006: 6, k007: 7, k008: 8, k009: 9,
|
||||
k010: 10, k011: 11, k012: 12, k013: 13, k014: 14, k015: 15, k016: 16, k017: 17, k018: 18, k019: 19,
|
||||
k020: 20, k021: 21, k022: 22, k023: 23, k024: 24, k025: 25, k026: 26, k027: 27, k028: 28, k029: 29,
|
||||
k030: 30, k031: 31, k032: 32, k033: 33, k034: 34, k035: 35, k036: 36, k037: 37, k038: 38, k039: 39,
|
||||
k040: 40, k041: 41, k042: 42, k043: 43, k044: 44, k045: 45, k046: 46, k047: 47, k048: 48, k049: 49,
|
||||
k050: 50, k051: 51, k052: 52, k053: 53, k054: 54, k055: 55, k056: 56, k057: 57, k058: 58, k059: 59,
|
||||
k060: 60, k061: 61, k062: 62, k063: 63, k064: 64, k065: 65, k066: 66, k067: 67, k068: 68, k069: 69,
|
||||
k070: 70, k071: 71, k072: 72, k073: 73, k074: 74, k075: 75, k076: 76, k077: 77, k078: 78, k079: 79,
|
||||
k080: 80, k081: 81, k082: 82, k083: 83, k084: 84, k085: 85, k086: 86, k087: 87, k088: 88, k089: 89,
|
||||
k090: 90, k091: 91, k092: 92, k093: 93, k094: 94, k095: 95, k096: 96, k097: 97, k098: 98, k099: 99,
|
||||
k100: 100, k101: 101, k102: 102, k103: 103, k104: 104, k105: 105, k106: 106, k107: 107, k108: 108, k109: 109,
|
||||
k110: 110, k111: 111, k112: 112, k113: 113, k114: 114, k115: 115, k116: 116, k117: 117, k118: 118, k119: 119,
|
||||
k120: 120, k121: 121, k122: 122, k123: 123, k124: 124, k125: 125, k126: 126, k127: 127, k128: 128, k129: 129,
|
||||
k130: 130, k131: 131, k132: 132, k133: 133, k134: 134, k135: 135, k136: 136, k137: 137, k138: 138, k139: 139,
|
||||
k140: 140, k141: 141, k142: 142, k143: 143, k144: 144, k145: 145, k146: 146, k147: 147, k148: 148, k149: 149,
|
||||
k150: 150, k151: 151, k152: 152, k153: 153, k154: 154, k155: 155, k156: 156, k157: 157, k158: 158, k159: 159,
|
||||
k160: 160, k161: 161, k162: 162, k163: 163, k164: 164, k165: 165, k166: 166, k167: 167, k168: 168, k169: 169,
|
||||
k170: 170, k171: 171, k172: 172, k173: 173, k174: 174, k175: 175, k176: 176, k177: 177, k178: 178, k179: 179,
|
||||
k180: 180, k181: 181, k182: 182, k183: 183, k184: 184, k185: 185, k186: 186, k187: 187, k188: 188, k189: 189,
|
||||
k190: 190, k191: 191, k192: 192, k193: 193, k194: 194, k195: 195, k196: 196, k197: 197, k198: 198, k199: 199,
|
||||
k200: 200, k201: 201, k202: 202, k203: 203, k204: 204, k205: 205, k206: 206, k207: 207, k208: 208, k209: 209,
|
||||
k210: 210, k211: 211, k212: 212, k213: 213, k214: 214, k215: 215, k216: 216, k217: 217, k218: 218, k219: 219,
|
||||
k220: 220, k221: 221, k222: 222, k223: 223, k224: 224, k225: 225, k226: 226, k227: 227, k228: 228, k229: 229,
|
||||
k230: 230, k231: 231, k232: 232, k233: 233, k234: 234, k235: 235, k236: 236, k237: 237, k238: 238, k239: 239,
|
||||
k240: 240, k241: 241, k242: 242, k243: 243, k244: 244, k245: 245, k246: 246, k247: 247, k248: 248, k249: 249,
|
||||
k250: 250, k251: 251, k252: 252, k253: 253, k254: 254, k255: 255, k256: 256
|
||||
}
|
||||
var keys = array(obj)
|
||||
assert_eq(length(keys), 257, "should have 257 keys")
|
||||
assert_eq(obj.k000, 0, "first key")
|
||||
assert_eq(obj.k256, 256, "last key")
|
||||
})
|
||||
|
||||
// Test: object with 100 function values
|
||||
run("object literal 100 function values", function() {
|
||||
var obj = {
|
||||
f000: function() { return 0 }, f001: function() { return 1 }, f002: function() { return 2 }, f003: function() { return 3 }, f004: function() { return 4 },
|
||||
f005: function() { return 5 }, f006: function() { return 6 }, f007: function() { return 7 }, f008: function() { return 8 }, f009: function() { return 9 },
|
||||
f010: function() { return 10 }, f011: function() { return 11 }, f012: function() { return 12 }, f013: function() { return 13 }, f014: function() { return 14 },
|
||||
f015: function() { return 15 }, f016: function() { return 16 }, f017: function() { return 17 }, f018: function() { return 18 }, f019: function() { return 19 },
|
||||
f020: function() { return 20 }, f021: function() { return 21 }, f022: function() { return 22 }, f023: function() { return 23 }, f024: function() { return 24 },
|
||||
f025: function() { return 25 }, f026: function() { return 26 }, f027: function() { return 27 }, f028: function() { return 28 }, f029: function() { return 29 },
|
||||
f030: function() { return 30 }, f031: function() { return 31 }, f032: function() { return 32 }, f033: function() { return 33 }, f034: function() { return 34 },
|
||||
f035: function() { return 35 }, f036: function() { return 36 }, f037: function() { return 37 }, f038: function() { return 38 }, f039: function() { return 39 },
|
||||
f040: function() { return 40 }, f041: function() { return 41 }, f042: function() { return 42 }, f043: function() { return 43 }, f044: function() { return 44 },
|
||||
f045: function() { return 45 }, f046: function() { return 46 }, f047: function() { return 47 }, f048: function() { return 48 }, f049: function() { return 49 },
|
||||
f050: function() { return 50 }, f051: function() { return 51 }, f052: function() { return 52 }, f053: function() { return 53 }, f054: function() { return 54 },
|
||||
f055: function() { return 55 }, f056: function() { return 56 }, f057: function() { return 57 }, f058: function() { return 58 }, f059: function() { return 59 },
|
||||
f060: function() { return 60 }, f061: function() { return 61 }, f062: function() { return 62 }, f063: function() { return 63 }, f064: function() { return 64 },
|
||||
f065: function() { return 65 }, f066: function() { return 66 }, f067: function() { return 67 }, f068: function() { return 68 }, f069: function() { return 69 },
|
||||
f070: function() { return 70 }, f071: function() { return 71 }, f072: function() { return 72 }, f073: function() { return 73 }, f074: function() { return 74 },
|
||||
f075: function() { return 75 }, f076: function() { return 76 }, f077: function() { return 77 }, f078: function() { return 78 }, f079: function() { return 79 },
|
||||
f080: function() { return 80 }, f081: function() { return 81 }, f082: function() { return 82 }, f083: function() { return 83 }, f084: function() { return 84 },
|
||||
f085: function() { return 85 }, f086: function() { return 86 }, f087: function() { return 87 }, f088: function() { return 88 }, f089: function() { return 89 },
|
||||
f090: function() { return 90 }, f091: function() { return 91 }, f092: function() { return 92 }, f093: function() { return 93 }, f094: function() { return 94 },
|
||||
f095: function() { return 95 }, f096: function() { return 96 }, f097: function() { return 97 }, f098: function() { return 98 }, f099: function() { return 99 }
|
||||
}
|
||||
var keys = array(obj)
|
||||
var i = 0
|
||||
var bad_count = 0
|
||||
assert_eq(length(keys), 100, "should have 100 keys")
|
||||
for (i = 0; i < length(keys); i++) {
|
||||
if (!is_function(obj[keys[i]])) {
|
||||
bad_count = bad_count + 1
|
||||
}
|
||||
}
|
||||
assert_eq(bad_count, 0, "all 100 values should be functions")
|
||||
assert_eq(obj.f000(), 0, "first fn returns 0")
|
||||
assert_eq(obj.f099(), 99, "last fn returns 99")
|
||||
})
|
||||
|
||||
// Test: object with 256 function values - exact boundary
|
||||
run("object literal 256 function values", function() {
|
||||
var obj = {
|
||||
f000: function() { return 0 }, f001: function() { return 1 }, f002: function() { return 2 }, f003: function() { return 3 }, f004: function() { return 4 },
|
||||
f005: function() { return 5 }, f006: function() { return 6 }, f007: function() { return 7 }, f008: function() { return 8 }, f009: function() { return 9 },
|
||||
f010: function() { return 10 }, f011: function() { return 11 }, f012: function() { return 12 }, f013: function() { return 13 }, f014: function() { return 14 },
|
||||
f015: function() { return 15 }, f016: function() { return 16 }, f017: function() { return 17 }, f018: function() { return 18 }, f019: function() { return 19 },
|
||||
f020: function() { return 20 }, f021: function() { return 21 }, f022: function() { return 22 }, f023: function() { return 23 }, f024: function() { return 24 },
|
||||
f025: function() { return 25 }, f026: function() { return 26 }, f027: function() { return 27 }, f028: function() { return 28 }, f029: function() { return 29 },
|
||||
f030: function() { return 30 }, f031: function() { return 31 }, f032: function() { return 32 }, f033: function() { return 33 }, f034: function() { return 34 },
|
||||
f035: function() { return 35 }, f036: function() { return 36 }, f037: function() { return 37 }, f038: function() { return 38 }, f039: function() { return 39 },
|
||||
f040: function() { return 40 }, f041: function() { return 41 }, f042: function() { return 42 }, f043: function() { return 43 }, f044: function() { return 44 },
|
||||
f045: function() { return 45 }, f046: function() { return 46 }, f047: function() { return 47 }, f048: function() { return 48 }, f049: function() { return 49 },
|
||||
f050: function() { return 50 }, f051: function() { return 51 }, f052: function() { return 52 }, f053: function() { return 53 }, f054: function() { return 54 },
|
||||
f055: function() { return 55 }, f056: function() { return 56 }, f057: function() { return 57 }, f058: function() { return 58 }, f059: function() { return 59 },
|
||||
f060: function() { return 60 }, f061: function() { return 61 }, f062: function() { return 62 }, f063: function() { return 63 }, f064: function() { return 64 },
|
||||
f065: function() { return 65 }, f066: function() { return 66 }, f067: function() { return 67 }, f068: function() { return 68 }, f069: function() { return 69 },
|
||||
f070: function() { return 70 }, f071: function() { return 71 }, f072: function() { return 72 }, f073: function() { return 73 }, f074: function() { return 74 },
|
||||
f075: function() { return 75 }, f076: function() { return 76 }, f077: function() { return 77 }, f078: function() { return 78 }, f079: function() { return 79 },
|
||||
f080: function() { return 80 }, f081: function() { return 81 }, f082: function() { return 82 }, f083: function() { return 83 }, f084: function() { return 84 },
|
||||
f085: function() { return 85 }, f086: function() { return 86 }, f087: function() { return 87 }, f088: function() { return 88 }, f089: function() { return 89 },
|
||||
f090: function() { return 90 }, f091: function() { return 91 }, f092: function() { return 92 }, f093: function() { return 93 }, f094: function() { return 94 },
|
||||
f095: function() { return 95 }, f096: function() { return 96 }, f097: function() { return 97 }, f098: function() { return 98 }, f099: function() { return 99 },
|
||||
f100: function() { return 100 }, f101: function() { return 101 }, f102: function() { return 102 }, f103: function() { return 103 }, f104: function() { return 104 },
|
||||
f105: function() { return 105 }, f106: function() { return 106 }, f107: function() { return 107 }, f108: function() { return 108 }, f109: function() { return 109 },
|
||||
f110: function() { return 110 }, f111: function() { return 111 }, f112: function() { return 112 }, f113: function() { return 113 }, f114: function() { return 114 },
|
||||
f115: function() { return 115 }, f116: function() { return 116 }, f117: function() { return 117 }, f118: function() { return 118 }, f119: function() { return 119 },
|
||||
f120: function() { return 120 }, f121: function() { return 121 }, f122: function() { return 122 }, f123: function() { return 123 }, f124: function() { return 124 },
|
||||
f125: function() { return 125 }, f126: function() { return 126 }, f127: function() { return 127 }, f128: function() { return 128 }, f129: function() { return 129 },
|
||||
f130: function() { return 130 }, f131: function() { return 131 }, f132: function() { return 132 }, f133: function() { return 133 }, f134: function() { return 134 },
|
||||
f135: function() { return 135 }, f136: function() { return 136 }, f137: function() { return 137 }, f138: function() { return 138 }, f139: function() { return 139 },
|
||||
f140: function() { return 140 }, f141: function() { return 141 }, f142: function() { return 142 }, f143: function() { return 143 }, f144: function() { return 144 },
|
||||
f145: function() { return 145 }, f146: function() { return 146 }, f147: function() { return 147 }, f148: function() { return 148 }, f149: function() { return 149 },
|
||||
f150: function() { return 150 }, f151: function() { return 151 }, f152: function() { return 152 }, f153: function() { return 153 }, f154: function() { return 154 },
|
||||
f155: function() { return 155 }, f156: function() { return 156 }, f157: function() { return 157 }, f158: function() { return 158 }, f159: function() { return 159 },
|
||||
f160: function() { return 160 }, f161: function() { return 161 }, f162: function() { return 162 }, f163: function() { return 163 }, f164: function() { return 164 },
|
||||
f165: function() { return 165 }, f166: function() { return 166 }, f167: function() { return 167 }, f168: function() { return 168 }, f169: function() { return 169 },
|
||||
f170: function() { return 170 }, f171: function() { return 171 }, f172: function() { return 172 }, f173: function() { return 173 }, f174: function() { return 174 },
|
||||
f175: function() { return 175 }, f176: function() { return 176 }, f177: function() { return 177 }, f178: function() { return 178 }, f179: function() { return 179 },
|
||||
f180: function() { return 180 }, f181: function() { return 181 }, f182: function() { return 182 }, f183: function() { return 183 }, f184: function() { return 184 },
|
||||
f185: function() { return 185 }, f186: function() { return 186 }, f187: function() { return 187 }, f188: function() { return 188 }, f189: function() { return 189 },
|
||||
f190: function() { return 190 }, f191: function() { return 191 }, f192: function() { return 192 }, f193: function() { return 193 }, f194: function() { return 194 },
|
||||
f195: function() { return 195 }, f196: function() { return 196 }, f197: function() { return 197 }, f198: function() { return 198 }, f199: function() { return 199 },
|
||||
f200: function() { return 200 }, f201: function() { return 201 }, f202: function() { return 202 }, f203: function() { return 203 }, f204: function() { return 204 },
|
||||
f205: function() { return 205 }, f206: function() { return 206 }, f207: function() { return 207 }, f208: function() { return 208 }, f209: function() { return 209 },
|
||||
f210: function() { return 210 }, f211: function() { return 211 }, f212: function() { return 212 }, f213: function() { return 213 }, f214: function() { return 214 },
|
||||
f215: function() { return 215 }, f216: function() { return 216 }, f217: function() { return 217 }, f218: function() { return 218 }, f219: function() { return 219 },
|
||||
f220: function() { return 220 }, f221: function() { return 221 }, f222: function() { return 222 }, f223: function() { return 223 }, f224: function() { return 224 },
|
||||
f225: function() { return 225 }, f226: function() { return 226 }, f227: function() { return 227 }, f228: function() { return 228 }, f229: function() { return 229 },
|
||||
f230: function() { return 230 }, f231: function() { return 231 }, f232: function() { return 232 }, f233: function() { return 233 }, f234: function() { return 234 },
|
||||
f235: function() { return 235 }, f236: function() { return 236 }, f237: function() { return 237 }, f238: function() { return 238 }, f239: function() { return 239 },
|
||||
f240: function() { return 240 }, f241: function() { return 241 }, f242: function() { return 242 }, f243: function() { return 243 }, f244: function() { return 244 },
|
||||
f245: function() { return 245 }, f246: function() { return 246 }, f247: function() { return 247 }, f248: function() { return 248 }, f249: function() { return 249 },
|
||||
f250: function() { return 250 }, f251: function() { return 251 }, f252: function() { return 252 }, f253: function() { return 253 }, f254: function() { return 254 },
|
||||
f255: function() { return 255 }
|
||||
}
|
||||
var keys = array(obj)
|
||||
var i = 0
|
||||
var bad_count = 0
|
||||
var first_bad = ""
|
||||
assert_eq(length(keys), 256, "should have 256 keys")
|
||||
for (i = 0; i < length(keys); i++) {
|
||||
if (!is_function(obj[keys[i]])) {
|
||||
if (first_bad == "") {
|
||||
first_bad = keys[i]
|
||||
}
|
||||
bad_count = bad_count + 1
|
||||
}
|
||||
}
|
||||
if (bad_count > 0) {
|
||||
fail(text(bad_count) + " of 256 values not functions, first bad: " + first_bad)
|
||||
}
|
||||
})
|
||||
|
||||
// Test: object with 300 function values - well past boundary
|
||||
run("object literal 300 function values", function() {
|
||||
var obj = {
|
||||
f000: function() { return 0 }, f001: function() { return 1 }, f002: function() { return 2 }, f003: function() { return 3 }, f004: function() { return 4 },
|
||||
f005: function() { return 5 }, f006: function() { return 6 }, f007: function() { return 7 }, f008: function() { return 8 }, f009: function() { return 9 },
|
||||
f010: function() { return 10 }, f011: function() { return 11 }, f012: function() { return 12 }, f013: function() { return 13 }, f014: function() { return 14 },
|
||||
f015: function() { return 15 }, f016: function() { return 16 }, f017: function() { return 17 }, f018: function() { return 18 }, f019: function() { return 19 },
|
||||
f020: function() { return 20 }, f021: function() { return 21 }, f022: function() { return 22 }, f023: function() { return 23 }, f024: function() { return 24 },
|
||||
f025: function() { return 25 }, f026: function() { return 26 }, f027: function() { return 27 }, f028: function() { return 28 }, f029: function() { return 29 },
|
||||
f030: function() { return 30 }, f031: function() { return 31 }, f032: function() { return 32 }, f033: function() { return 33 }, f034: function() { return 34 },
|
||||
f035: function() { return 35 }, f036: function() { return 36 }, f037: function() { return 37 }, f038: function() { return 38 }, f039: function() { return 39 },
|
||||
f040: function() { return 40 }, f041: function() { return 41 }, f042: function() { return 42 }, f043: function() { return 43 }, f044: function() { return 44 },
|
||||
f045: function() { return 45 }, f046: function() { return 46 }, f047: function() { return 47 }, f048: function() { return 48 }, f049: function() { return 49 },
|
||||
f050: function() { return 50 }, f051: function() { return 51 }, f052: function() { return 52 }, f053: function() { return 53 }, f054: function() { return 54 },
|
||||
f055: function() { return 55 }, f056: function() { return 56 }, f057: function() { return 57 }, f058: function() { return 58 }, f059: function() { return 59 },
|
||||
f060: function() { return 60 }, f061: function() { return 61 }, f062: function() { return 62 }, f063: function() { return 63 }, f064: function() { return 64 },
|
||||
f065: function() { return 65 }, f066: function() { return 66 }, f067: function() { return 67 }, f068: function() { return 68 }, f069: function() { return 69 },
|
||||
f070: function() { return 70 }, f071: function() { return 71 }, f072: function() { return 72 }, f073: function() { return 73 }, f074: function() { return 74 },
|
||||
f075: function() { return 75 }, f076: function() { return 76 }, f077: function() { return 77 }, f078: function() { return 78 }, f079: function() { return 79 },
|
||||
f080: function() { return 80 }, f081: function() { return 81 }, f082: function() { return 82 }, f083: function() { return 83 }, f084: function() { return 84 },
|
||||
f085: function() { return 85 }, f086: function() { return 86 }, f087: function() { return 87 }, f088: function() { return 88 }, f089: function() { return 89 },
|
||||
f090: function() { return 90 }, f091: function() { return 91 }, f092: function() { return 92 }, f093: function() { return 93 }, f094: function() { return 94 },
|
||||
f095: function() { return 95 }, f096: function() { return 96 }, f097: function() { return 97 }, f098: function() { return 98 }, f099: function() { return 99 },
|
||||
f100: function() { return 100 }, f101: function() { return 101 }, f102: function() { return 102 }, f103: function() { return 103 }, f104: function() { return 104 },
|
||||
f105: function() { return 105 }, f106: function() { return 106 }, f107: function() { return 107 }, f108: function() { return 108 }, f109: function() { return 109 },
|
||||
f110: function() { return 110 }, f111: function() { return 111 }, f112: function() { return 112 }, f113: function() { return 113 }, f114: function() { return 114 },
|
||||
f115: function() { return 115 }, f116: function() { return 116 }, f117: function() { return 117 }, f118: function() { return 118 }, f119: function() { return 119 },
|
||||
f120: function() { return 120 }, f121: function() { return 121 }, f122: function() { return 122 }, f123: function() { return 123 }, f124: function() { return 124 },
|
||||
f125: function() { return 125 }, f126: function() { return 126 }, f127: function() { return 127 }, f128: function() { return 128 }, f129: function() { return 129 },
|
||||
f130: function() { return 130 }, f131: function() { return 131 }, f132: function() { return 132 }, f133: function() { return 133 }, f134: function() { return 134 },
|
||||
f135: function() { return 135 }, f136: function() { return 136 }, f137: function() { return 137 }, f138: function() { return 138 }, f139: function() { return 139 },
|
||||
f140: function() { return 140 }, f141: function() { return 141 }, f142: function() { return 142 }, f143: function() { return 143 }, f144: function() { return 144 },
|
||||
f145: function() { return 145 }, f146: function() { return 146 }, f147: function() { return 147 }, f148: function() { return 148 }, f149: function() { return 149 },
|
||||
f150: function() { return 150 }, f151: function() { return 151 }, f152: function() { return 152 }, f153: function() { return 153 }, f154: function() { return 154 },
|
||||
f155: function() { return 155 }, f156: function() { return 156 }, f157: function() { return 157 }, f158: function() { return 158 }, f159: function() { return 159 },
|
||||
f160: function() { return 160 }, f161: function() { return 161 }, f162: function() { return 162 }, f163: function() { return 163 }, f164: function() { return 164 },
|
||||
f165: function() { return 165 }, f166: function() { return 166 }, f167: function() { return 167 }, f168: function() { return 168 }, f169: function() { return 169 },
|
||||
f170: function() { return 170 }, f171: function() { return 171 }, f172: function() { return 172 }, f173: function() { return 173 }, f174: function() { return 174 },
|
||||
f175: function() { return 175 }, f176: function() { return 176 }, f177: function() { return 177 }, f178: function() { return 178 }, f179: function() { return 179 },
|
||||
f180: function() { return 180 }, f181: function() { return 181 }, f182: function() { return 182 }, f183: function() { return 183 }, f184: function() { return 184 },
|
||||
f185: function() { return 185 }, f186: function() { return 186 }, f187: function() { return 187 }, f188: function() { return 188 }, f189: function() { return 189 },
|
||||
f190: function() { return 190 }, f191: function() { return 191 }, f192: function() { return 192 }, f193: function() { return 193 }, f194: function() { return 194 },
|
||||
f195: function() { return 195 }, f196: function() { return 196 }, f197: function() { return 197 }, f198: function() { return 198 }, f199: function() { return 199 },
|
||||
f200: function() { return 200 }, f201: function() { return 201 }, f202: function() { return 202 }, f203: function() { return 203 }, f204: function() { return 204 },
|
||||
f205: function() { return 205 }, f206: function() { return 206 }, f207: function() { return 207 }, f208: function() { return 208 }, f209: function() { return 209 },
|
||||
f210: function() { return 210 }, f211: function() { return 211 }, f212: function() { return 212 }, f213: function() { return 213 }, f214: function() { return 214 },
|
||||
f215: function() { return 215 }, f216: function() { return 216 }, f217: function() { return 217 }, f218: function() { return 218 }, f219: function() { return 219 },
|
||||
f220: function() { return 220 }, f221: function() { return 221 }, f222: function() { return 222 }, f223: function() { return 223 }, f224: function() { return 224 },
|
||||
f225: function() { return 225 }, f226: function() { return 226 }, f227: function() { return 227 }, f228: function() { return 228 }, f229: function() { return 229 },
|
||||
f230: function() { return 230 }, f231: function() { return 231 }, f232: function() { return 232 }, f233: function() { return 233 }, f234: function() { return 234 },
|
||||
f235: function() { return 235 }, f236: function() { return 236 }, f237: function() { return 237 }, f238: function() { return 238 }, f239: function() { return 239 },
|
||||
f240: function() { return 240 }, f241: function() { return 241 }, f242: function() { return 242 }, f243: function() { return 243 }, f244: function() { return 244 },
|
||||
f245: function() { return 245 }, f246: function() { return 246 }, f247: function() { return 247 }, f248: function() { return 248 }, f249: function() { return 249 },
|
||||
f250: function() { return 250 }, f251: function() { return 251 }, f252: function() { return 252 }, f253: function() { return 253 }, f254: function() { return 254 },
|
||||
f255: function() { return 255 }, f256: function() { return 256 }, f257: function() { return 257 }, f258: function() { return 258 }, f259: function() { return 259 },
|
||||
f260: function() { return 260 }, f261: function() { return 261 }, f262: function() { return 262 }, f263: function() { return 263 }, f264: function() { return 264 },
|
||||
f265: function() { return 265 }, f266: function() { return 266 }, f267: function() { return 267 }, f268: function() { return 268 }, f269: function() { return 269 },
|
||||
f270: function() { return 270 }, f271: function() { return 271 }, f272: function() { return 272 }, f273: function() { return 273 }, f274: function() { return 274 },
|
||||
f275: function() { return 275 }, f276: function() { return 276 }, f277: function() { return 277 }, f278: function() { return 278 }, f279: function() { return 279 },
|
||||
f280: function() { return 280 }, f281: function() { return 281 }, f282: function() { return 282 }, f283: function() { return 283 }, f284: function() { return 284 },
|
||||
f285: function() { return 285 }, f286: function() { return 286 }, f287: function() { return 287 }, f288: function() { return 288 }, f289: function() { return 289 },
|
||||
f290: function() { return 290 }, f291: function() { return 291 }, f292: function() { return 292 }, f293: function() { return 293 }, f294: function() { return 294 },
|
||||
f295: function() { return 295 }, f296: function() { return 296 }, f297: function() { return 297 }, f298: function() { return 298 }, f299: function() { return 299 }
|
||||
}
|
||||
var keys = array(obj)
|
||||
var i = 0
|
||||
var bad_count = 0
|
||||
var first_bad = ""
|
||||
assert_eq(length(keys), 300, "should have 300 keys")
|
||||
for (i = 0; i < length(keys); i++) {
|
||||
if (!is_function(obj[keys[i]])) {
|
||||
if (first_bad == "") {
|
||||
first_bad = keys[i]
|
||||
}
|
||||
bad_count = bad_count + 1
|
||||
}
|
||||
}
|
||||
if (bad_count > 0) {
|
||||
fail(text(bad_count) + " of 300 values not functions, first bad: " + first_bad)
|
||||
}
|
||||
})
|
||||
|
||||
// Test: object built incrementally (not literal) with 300 keys
|
||||
run("object incremental 300 number keys", function() {
|
||||
var obj = {}
|
||||
var i = 0
|
||||
for (i = 0; i < 300; i++) {
|
||||
obj["k" + text(i)] = i
|
||||
}
|
||||
var keys = array(obj)
|
||||
assert_eq(length(keys), 300, "should have 300 keys")
|
||||
assert_eq(obj.k0, 0, "first key")
|
||||
assert_eq(obj.k299, 299, "last key")
|
||||
})
|
||||
|
||||
// Test: object built incrementally with 300 function values
|
||||
run("object incremental 300 function values", function() {
|
||||
var obj = {}
|
||||
var i = 0
|
||||
var make_fn = function(n) { return function() { return n } }
|
||||
for (i = 0; i < 300; i++) {
|
||||
obj["f" + text(i)] = make_fn(i)
|
||||
}
|
||||
var keys = array(obj)
|
||||
var bad_count = 0
|
||||
assert_eq(length(keys), 300, "should have 300 keys")
|
||||
for (i = 0; i < length(keys); i++) {
|
||||
if (!is_function(obj[keys[i]])) {
|
||||
bad_count = bad_count + 1
|
||||
}
|
||||
}
|
||||
assert_eq(bad_count, 0, "all 300 values should be functions")
|
||||
assert_eq(obj.f0(), 0, "first fn")
|
||||
assert_eq(obj.f299(), 299, "last fn")
|
||||
})
|
||||
|
||||
// Test: object with very long key names
|
||||
run("object literal long key names", function() {
|
||||
var obj = {
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_01: 1,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_02: 2,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_03: 3,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_04: 4,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_05: 5,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_06: 6,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_07: 7,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_08: 8,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_09: 9,
|
||||
this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_10: 10
|
||||
}
|
||||
var keys = array(obj)
|
||||
assert_eq(length(keys), 10, "should have 10 keys")
|
||||
assert_eq(obj.this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_01, 1, "long key 1")
|
||||
assert_eq(obj.this_is_a_really_long_key_name_that_tests_whether_long_identifiers_cause_issues_key_10, 10, "long key 10")
|
||||
})
|
||||
|
||||
// Test: return object literal from function with many keys
|
||||
run("object literal 300 function values returned from function", function() {
|
||||
var make_obj = function() {
|
||||
return {
|
||||
f000: function() { return 0 }, f001: function() { return 1 }, f002: function() { return 2 }, f003: function() { return 3 }, f004: function() { return 4 },
|
||||
f005: function() { return 5 }, f006: function() { return 6 }, f007: function() { return 7 }, f008: function() { return 8 }, f009: function() { return 9 },
|
||||
f010: function() { return 10 }, f011: function() { return 11 }, f012: function() { return 12 }, f013: function() { return 13 }, f014: function() { return 14 },
|
||||
f015: function() { return 15 }, f016: function() { return 16 }, f017: function() { return 17 }, f018: function() { return 18 }, f019: function() { return 19 },
|
||||
f020: function() { return 20 }, f021: function() { return 21 }, f022: function() { return 22 }, f023: function() { return 23 }, f024: function() { return 24 },
|
||||
f025: function() { return 25 }, f026: function() { return 26 }, f027: function() { return 27 }, f028: function() { return 28 }, f029: function() { return 29 },
|
||||
f030: function() { return 30 }, f031: function() { return 31 }, f032: function() { return 32 }, f033: function() { return 33 }, f034: function() { return 34 },
|
||||
f035: function() { return 35 }, f036: function() { return 36 }, f037: function() { return 37 }, f038: function() { return 38 }, f039: function() { return 39 },
|
||||
f040: function() { return 40 }, f041: function() { return 41 }, f042: function() { return 42 }, f043: function() { return 43 }, f044: function() { return 44 },
|
||||
f045: function() { return 45 }, f046: function() { return 46 }, f047: function() { return 47 }, f048: function() { return 48 }, f049: function() { return 49 },
|
||||
f050: function() { return 50 }, f051: function() { return 51 }, f052: function() { return 52 }, f053: function() { return 53 }, f054: function() { return 54 },
|
||||
f055: function() { return 55 }, f056: function() { return 56 }, f057: function() { return 57 }, f058: function() { return 58 }, f059: function() { return 59 },
|
||||
f060: function() { return 60 }, f061: function() { return 61 }, f062: function() { return 62 }, f063: function() { return 63 }, f064: function() { return 64 },
|
||||
f065: function() { return 65 }, f066: function() { return 66 }, f067: function() { return 67 }, f068: function() { return 68 }, f069: function() { return 69 },
|
||||
f070: function() { return 70 }, f071: function() { return 71 }, f072: function() { return 72 }, f073: function() { return 73 }, f074: function() { return 74 },
|
||||
f075: function() { return 75 }, f076: function() { return 76 }, f077: function() { return 77 }, f078: function() { return 78 }, f079: function() { return 79 },
|
||||
f080: function() { return 80 }, f081: function() { return 81 }, f082: function() { return 82 }, f083: function() { return 83 }, f084: function() { return 84 },
|
||||
f085: function() { return 85 }, f086: function() { return 86 }, f087: function() { return 87 }, f088: function() { return 88 }, f089: function() { return 89 },
|
||||
f090: function() { return 90 }, f091: function() { return 91 }, f092: function() { return 92 }, f093: function() { return 93 }, f094: function() { return 94 },
|
||||
f095: function() { return 95 }, f096: function() { return 96 }, f097: function() { return 97 }, f098: function() { return 98 }, f099: function() { return 99 },
|
||||
f100: function() { return 100 }, f101: function() { return 101 }, f102: function() { return 102 }, f103: function() { return 103 }, f104: function() { return 104 },
|
||||
f105: function() { return 105 }, f106: function() { return 106 }, f107: function() { return 107 }, f108: function() { return 108 }, f109: function() { return 109 },
|
||||
f110: function() { return 110 }, f111: function() { return 111 }, f112: function() { return 112 }, f113: function() { return 113 }, f114: function() { return 114 },
|
||||
f115: function() { return 115 }, f116: function() { return 116 }, f117: function() { return 117 }, f118: function() { return 118 }, f119: function() { return 119 },
|
||||
f120: function() { return 120 }, f121: function() { return 121 }, f122: function() { return 122 }, f123: function() { return 123 }, f124: function() { return 124 },
|
||||
f125: function() { return 125 }, f126: function() { return 126 }, f127: function() { return 127 }, f128: function() { return 128 }, f129: function() { return 129 },
|
||||
f130: function() { return 130 }, f131: function() { return 131 }, f132: function() { return 132 }, f133: function() { return 133 }, f134: function() { return 134 },
|
||||
f135: function() { return 135 }, f136: function() { return 136 }, f137: function() { return 137 }, f138: function() { return 138 }, f139: function() { return 139 },
|
||||
f140: function() { return 140 }, f141: function() { return 141 }, f142: function() { return 142 }, f143: function() { return 143 }, f144: function() { return 144 },
|
||||
f145: function() { return 145 }, f146: function() { return 146 }, f147: function() { return 147 }, f148: function() { return 148 }, f149: function() { return 149 },
|
||||
f150: function() { return 150 }, f151: function() { return 151 }, f152: function() { return 152 }, f153: function() { return 153 }, f154: function() { return 154 },
|
||||
f155: function() { return 155 }, f156: function() { return 156 }, f157: function() { return 157 }, f158: function() { return 158 }, f159: function() { return 159 },
|
||||
f160: function() { return 160 }, f161: function() { return 161 }, f162: function() { return 162 }, f163: function() { return 163 }, f164: function() { return 164 },
|
||||
f165: function() { return 165 }, f166: function() { return 166 }, f167: function() { return 167 }, f168: function() { return 168 }, f169: function() { return 169 },
|
||||
f170: function() { return 170 }, f171: function() { return 171 }, f172: function() { return 172 }, f173: function() { return 173 }, f174: function() { return 174 },
|
||||
f175: function() { return 175 }, f176: function() { return 176 }, f177: function() { return 177 }, f178: function() { return 178 }, f179: function() { return 179 },
|
||||
f180: function() { return 180 }, f181: function() { return 181 }, f182: function() { return 182 }, f183: function() { return 183 }, f184: function() { return 184 },
|
||||
f185: function() { return 185 }, f186: function() { return 186 }, f187: function() { return 187 }, f188: function() { return 188 }, f189: function() { return 189 },
|
||||
f190: function() { return 190 }, f191: function() { return 191 }, f192: function() { return 192 }, f193: function() { return 193 }, f194: function() { return 194 },
|
||||
f195: function() { return 195 }, f196: function() { return 196 }, f197: function() { return 197 }, f198: function() { return 198 }, f199: function() { return 199 },
|
||||
f200: function() { return 200 }, f201: function() { return 201 }, f202: function() { return 202 }, f203: function() { return 203 }, f204: function() { return 204 },
|
||||
f205: function() { return 205 }, f206: function() { return 206 }, f207: function() { return 207 }, f208: function() { return 208 }, f209: function() { return 209 },
|
||||
f210: function() { return 210 }, f211: function() { return 211 }, f212: function() { return 212 }, f213: function() { return 213 }, f214: function() { return 214 },
|
||||
f215: function() { return 215 }, f216: function() { return 216 }, f217: function() { return 217 }, f218: function() { return 218 }, f219: function() { return 219 },
|
||||
f220: function() { return 220 }, f221: function() { return 221 }, f222: function() { return 222 }, f223: function() { return 223 }, f224: function() { return 224 },
|
||||
f225: function() { return 225 }, f226: function() { return 226 }, f227: function() { return 227 }, f228: function() { return 228 }, f229: function() { return 229 },
|
||||
f230: function() { return 230 }, f231: function() { return 231 }, f232: function() { return 232 }, f233: function() { return 233 }, f234: function() { return 234 },
|
||||
f235: function() { return 235 }, f236: function() { return 236 }, f237: function() { return 237 }, f238: function() { return 238 }, f239: function() { return 239 },
|
||||
f240: function() { return 240 }, f241: function() { return 241 }, f242: function() { return 242 }, f243: function() { return 243 }, f244: function() { return 244 },
|
||||
f245: function() { return 245 }, f246: function() { return 246 }, f247: function() { return 247 }, f248: function() { return 248 }, f249: function() { return 249 },
|
||||
f250: function() { return 250 }, f251: function() { return 251 }, f252: function() { return 252 }, f253: function() { return 253 }, f254: function() { return 254 },
|
||||
f255: function() { return 255 }, f256: function() { return 256 }, f257: function() { return 257 }, f258: function() { return 258 }, f259: function() { return 259 },
|
||||
f260: function() { return 260 }, f261: function() { return 261 }, f262: function() { return 262 }, f263: function() { return 263 }, f264: function() { return 264 },
|
||||
f265: function() { return 265 }, f266: function() { return 266 }, f267: function() { return 267 }, f268: function() { return 268 }, f269: function() { return 269 },
|
||||
f270: function() { return 270 }, f271: function() { return 271 }, f272: function() { return 272 }, f273: function() { return 273 }, f274: function() { return 274 },
|
||||
f275: function() { return 275 }, f276: function() { return 276 }, f277: function() { return 277 }, f278: function() { return 278 }, f279: function() { return 279 },
|
||||
f280: function() { return 280 }, f281: function() { return 281 }, f282: function() { return 282 }, f283: function() { return 283 }, f284: function() { return 284 },
|
||||
f285: function() { return 285 }, f286: function() { return 286 }, f287: function() { return 287 }, f288: function() { return 288 }, f289: function() { return 289 },
|
||||
f290: function() { return 290 }, f291: function() { return 291 }, f292: function() { return 292 }, f293: function() { return 293 }, f294: function() { return 294 },
|
||||
f295: function() { return 295 }, f296: function() { return 296 }, f297: function() { return 297 }, f298: function() { return 298 }, f299: function() { return 299 }
|
||||
}
|
||||
}
|
||||
var obj = make_obj()
|
||||
var keys = array(obj)
|
||||
var i = 0
|
||||
var bad_count = 0
|
||||
var first_bad = ""
|
||||
assert_eq(length(keys), 300, "should have 300 keys")
|
||||
for (i = 0; i < length(keys); i++) {
|
||||
if (!is_function(obj[keys[i]])) {
|
||||
if (first_bad == "") {
|
||||
first_bad = keys[i]
|
||||
}
|
||||
bad_count = bad_count + 1
|
||||
}
|
||||
}
|
||||
if (bad_count > 0) {
|
||||
fail(text(bad_count) + " of 300 values not functions, first bad: " + first_bad)
|
||||
}
|
||||
})
|
||||
|
||||
// ============================================================================
|
||||
// SUMMARY
|
||||
// ============================================================================
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
var f = x => { return x }; f(1)
|
||||
@@ -1 +0,0 @@
|
||||
var f = (x = 10) => x; f()
|
||||
@@ -1 +0,0 @@
|
||||
var f = x => x * 2; f(5)
|
||||
@@ -1 +0,0 @@
|
||||
var f = (a, b) => a + b; f(2, 3)
|
||||
@@ -1 +0,0 @@
|
||||
var f = () => 42; f()
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; x += 3; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 7; x &= 3; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 6; x /= 2; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; x &&= 10; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 0; x ||= 10; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 7; x %= 3; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; x *= 3; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = null; x ??= 10; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; x |= 2; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 2; x **= 3; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 2; x <<= 3; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 8; x >>= 2; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = -8; x >>>= 2; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; x -= 3; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; x ^= 3; x
|
||||
@@ -1 +0,0 @@
|
||||
var x, y; x = y = 5; x + y
|
||||
@@ -1 +0,0 @@
|
||||
var f = function(x) { return function() { return x } }; f(5)()
|
||||
@@ -1,11 +0,0 @@
|
||||
var counter = function() {
|
||||
var n = 0
|
||||
return function() {
|
||||
n = n + 1
|
||||
return n
|
||||
}
|
||||
}
|
||||
var c = counter()
|
||||
c()
|
||||
c()
|
||||
c()
|
||||
@@ -1,3 +0,0 @@
|
||||
// simple test that comments work
|
||||
var x = 5
|
||||
// other comment
|
||||
@@ -1 +0,0 @@
|
||||
/* comment */ 5
|
||||
@@ -1 +0,0 @@
|
||||
1 /* a */ + /* b */ 2
|
||||
@@ -1 +0,0 @@
|
||||
def x = 5; x
|
||||
@@ -1 +0,0 @@
|
||||
var i = 0; do { i = i + 1 } while (i < 3); i
|
||||
@@ -1 +0,0 @@
|
||||
var s = 0; var i = 0; do { i = i + 1; if (i == 2) continue; s = s + i } while (i < 5); s
|
||||
@@ -1 +0,0 @@
|
||||
;;; 5
|
||||
@@ -1 +0,0 @@
|
||||
var s = 0; for (var i = 0; i < 3; i++) s = s + i; s
|
||||
@@ -1 +0,0 @@
|
||||
var s = 0; for (var i = 0; i < 10; i++) { if (i == 4) break; s = s + i }; s
|
||||
@@ -1 +0,0 @@
|
||||
var s = 0; for (var i = 0; i < 5; i++) { if (i == 2) continue; s = s + i }; s
|
||||
@@ -1 +0,0 @@
|
||||
var f = function(x) { return x * 2 }; f(3)
|
||||
@@ -1 +0,0 @@
|
||||
(function(x) { return x * 2 })(5)
|
||||
@@ -1 +0,0 @@
|
||||
function fac(n) { if (n <= 1) return 1; return n * fac(n - 1) }; fac(5)
|
||||
@@ -1,2 +0,0 @@
|
||||
function a() { go b() }
|
||||
function b() { 1 }
|
||||
@@ -1,2 +0,0 @@
|
||||
var o = {m: function() { 1 }}
|
||||
function f() { go o.m() }
|
||||
@@ -1 +0,0 @@
|
||||
var x = 0; if (true) x = 1; x
|
||||
@@ -1 +0,0 @@
|
||||
if (false) 1 else 2
|
||||
@@ -1 +0,0 @@
|
||||
print("a")
|
||||
@@ -1 +0,0 @@
|
||||
var s = 0; outer: for (var i = 0; i < 3; i++) { for (var j = 0; j < 3; j++) { if (j == 1) continue outer; s = s + 1 } }; s
|
||||
@@ -1 +0,0 @@
|
||||
var x = 1, y = 2; x + y
|
||||
@@ -1 +0,0 @@
|
||||
var x = 1; { var y = 2; { var z = 3; x = x + y + z } }; x
|
||||
@@ -1 +0,0 @@
|
||||
0b1010
|
||||
@@ -1 +0,0 @@
|
||||
1e3
|
||||
@@ -1 +0,0 @@
|
||||
3.14
|
||||
@@ -1 +0,0 @@
|
||||
0xff
|
||||
@@ -1 +0,0 @@
|
||||
0o17
|
||||
@@ -1 +0,0 @@
|
||||
1_000_000
|
||||
@@ -1 +0,0 @@
|
||||
1 + 2 * 3
|
||||
@@ -1 +0,0 @@
|
||||
5 & 3
|
||||
@@ -1 +0,0 @@
|
||||
~5
|
||||
@@ -1 +0,0 @@
|
||||
5 | 2
|
||||
@@ -1 +0,0 @@
|
||||
5 ^ 3
|
||||
@@ -1 +0,0 @@
|
||||
(1, 2, 3)
|
||||
@@ -1 +0,0 @@
|
||||
5 > 3
|
||||
@@ -1 +0,0 @@
|
||||
3 == 3
|
||||
@@ -1 +0,0 @@
|
||||
5 >= 5
|
||||
@@ -1 +0,0 @@
|
||||
3 < 5
|
||||
@@ -1 +0,0 @@
|
||||
3 <= 3
|
||||
@@ -1 +0,0 @@
|
||||
3 != 4
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; x--; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; --x
|
||||
@@ -1 +0,0 @@
|
||||
var o = {x: 1}; delete o.x; o.x
|
||||
@@ -1 +0,0 @@
|
||||
var o = {x: 1}; "x" in o
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; x++; x
|
||||
@@ -1 +0,0 @@
|
||||
var x = 5; ++x
|
||||
@@ -1 +0,0 @@
|
||||
true && false
|
||||
@@ -1 +0,0 @@
|
||||
!false
|
||||
@@ -1 +0,0 @@
|
||||
false || true
|
||||
@@ -1 +0,0 @@
|
||||
null ?? 5
|
||||
@@ -1 +0,0 @@
|
||||
2 ** 3
|
||||
@@ -1 +0,0 @@
|
||||
2 << 3
|
||||
@@ -1 +0,0 @@
|
||||
8 >> 2
|
||||
@@ -1 +0,0 @@
|
||||
-8 >>> 2
|
||||
@@ -1 +0,0 @@
|
||||
true ? 1 : 2
|
||||
@@ -1 +0,0 @@
|
||||
-5
|
||||
@@ -1 +0,0 @@
|
||||
+"5"
|
||||
@@ -1 +0,0 @@
|
||||
var o = {a: 1}; o?.["a"]
|
||||
@@ -1 +0,0 @@
|
||||
var o = {f: () => 1}; o.f?.()
|
||||
@@ -1 +0,0 @@
|
||||
var o = null; o?.a
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user