add object literal test
This commit is contained in:
12
fd.c
12
fd.c
@@ -668,17 +668,21 @@ JSC_CCALL(fd_realpath,
|
|||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
char resolved[PATH_MAX];
|
char resolved[PATH_MAX];
|
||||||
DWORD len = GetFullPathNameA(path, PATH_MAX, resolved, NULL);
|
DWORD len = GetFullPathNameA(path, PATH_MAX, resolved, NULL);
|
||||||
JS_FreeCString(js, path);
|
|
||||||
if (len == 0 || len >= PATH_MAX) {
|
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);
|
return JS_NewString(js, resolved);
|
||||||
#else
|
#else
|
||||||
char *resolved = realpath(path, NULL);
|
char *resolved = realpath(path, NULL);
|
||||||
JS_FreeCString(js, path);
|
|
||||||
if (!resolved) {
|
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);
|
JSValue result = JS_NewString(js, resolved);
|
||||||
free(resolved);
|
free(resolved);
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
111
internal/shop.cm
111
internal/shop.cm
@@ -80,12 +80,12 @@ function get_packages_dir() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get the core directory (in the global shop)
|
// Get the core directory (in the global shop)
|
||||||
|
var core_package = 'core'
|
||||||
|
|
||||||
Shop.get_core_dir = function() {
|
Shop.get_core_dir = function() {
|
||||||
return get_packages_dir() + '/' + core_package
|
return get_packages_dir() + '/' + core_package
|
||||||
}
|
}
|
||||||
|
|
||||||
var core_package = 'core'
|
|
||||||
|
|
||||||
// Get the links file path (in the global shop)
|
// Get the links file path (in the global shop)
|
||||||
function get_links_path() {
|
function get_links_path() {
|
||||||
return global_shop_path + '/link.toml'
|
return global_shop_path + '/link.toml'
|
||||||
@@ -400,98 +400,54 @@ Shop.get_script_capabilities = function(path) {
|
|||||||
return Shop.script_inject_for(file_info)
|
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) {
|
function inject_env(inject) {
|
||||||
// Start with runtime functions from engine
|
|
||||||
var env = {}
|
var env = {}
|
||||||
var rt = my$_.os ? my$_.os.runtime_env : null
|
var rt = my$_.os ? my$_.os.runtime_env : null
|
||||||
if (rt) {
|
if (rt) {
|
||||||
arrfor(array(rt), function(k) { env[k] = rt[k] })
|
arrfor(array(rt), function(k) { env[k] = rt[k] })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add capability injections
|
// Add capability injections with $ prefix
|
||||||
var i = 0
|
var i = 0
|
||||||
var inj = null
|
var inj = null
|
||||||
var key = null
|
var key = null
|
||||||
for (i = 0; i < length(inject); i++) {
|
for (i = 0; i < length(inject); i++) {
|
||||||
inj = inject[i]
|
inj = inject[i]
|
||||||
key = trim(inj, '$')
|
key = inj
|
||||||
if (key == 'fd') env[key] = fd
|
if (key && key[0] == '$') key = text(key, 1)
|
||||||
else env[key] = my$_[key]
|
if (key == 'fd') env['$fd'] = fd
|
||||||
|
else env['$' + key] = my$_[key]
|
||||||
}
|
}
|
||||||
return env
|
return env
|
||||||
}
|
}
|
||||||
|
|
||||||
function inject_bindings_code(inject) {
|
// Compile a module and return its bytecode blob.
|
||||||
var lines = []
|
// The bytecode is cached on disk by content hash.
|
||||||
|
|
||||||
// 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){\n" +
|
|
||||||
"def arg = args;\n" +
|
|
||||||
"def PACKAGE = " + pkg_arg + ";\n" +
|
|
||||||
binds + "\n" +
|
|
||||||
script + "\n" +
|
|
||||||
"})"
|
|
||||||
return fn
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve module function, hashing it in the process
|
|
||||||
// path is the exact path to the script file
|
|
||||||
function resolve_mod_fn(path, pkg) {
|
function resolve_mod_fn(path, pkg) {
|
||||||
if (!fd.is_file(path)) { print(`path ${path} is not a file`); disrupt }
|
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 content = text(fd.slurp(path))
|
||||||
var script = script_form(path, content, file_pkg, inject)
|
|
||||||
|
|
||||||
// Check cache for pre-compiled .mach blob
|
// 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) {
|
if (cached) {
|
||||||
return mach_load(cached)
|
return cached
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compile via new pipeline
|
// Compile via new pipeline
|
||||||
var ast = analyze(script, path)
|
ast = analyze(content, path)
|
||||||
var ast_json = shop_json.encode(ast)
|
ast_json = shop_json.encode(ast)
|
||||||
|
|
||||||
// Cache compiled binary
|
// Cache compiled binary
|
||||||
var compiled = mach_compile_ast(path, ast_json)
|
compiled = mach_compile_ast(path, ast_json)
|
||||||
put_into_cache(stone(blob(script)), compiled)
|
put_into_cache(stone(blob(content)), compiled)
|
||||||
|
|
||||||
// Evaluate to get the function object
|
return compiled
|
||||||
return mach_eval_ast(path, ast_json)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// given a path and a package context
|
// given a path and a package context
|
||||||
@@ -854,29 +810,26 @@ function execute_module(info)
|
|||||||
var mod_resolve = info.mod_resolve
|
var mod_resolve = info.mod_resolve
|
||||||
|
|
||||||
var used = null
|
var used = null
|
||||||
var context = null
|
|
||||||
var file_info = null
|
var file_info = null
|
||||||
var inject = null
|
var inject = null
|
||||||
var env = null
|
var env = null
|
||||||
var pkg = null
|
var pkg = null
|
||||||
var use_fn = null
|
|
||||||
|
|
||||||
if (mod_resolve.scope < 900) {
|
if (mod_resolve.scope < 900) {
|
||||||
context = null
|
// Build env with runtime fns, capabilities, and use function
|
||||||
if (c_resolve.scope < 900) {
|
|
||||||
context = call_c_module(c_resolve)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get file info to determine inject list
|
|
||||||
file_info = Shop.file_info(mod_resolve.path)
|
file_info = Shop.file_info(mod_resolve.path)
|
||||||
inject = Shop.script_inject_for(file_info)
|
inject = Shop.script_inject_for(file_info)
|
||||||
env = inject_env(inject)
|
env = inject_env(inject)
|
||||||
pkg = file_info.package
|
pkg = file_info.package
|
||||||
use_fn = make_use_fn(pkg)
|
env.use = make_use_fn(pkg)
|
||||||
|
|
||||||
// Call with signature: setup_module(args, use, env)
|
// Add C module as native context if available
|
||||||
// args is null for module loading
|
if (c_resolve.scope < 900) {
|
||||||
used = call(mod_resolve.symbol, context, [null, use_fn, env])
|
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) {
|
} else if (c_resolve.scope < 900) {
|
||||||
// C only
|
// C only
|
||||||
used = call_c_module(c_resolve)
|
used = call_c_module(c_resolve)
|
||||||
@@ -884,12 +837,8 @@ function execute_module(info)
|
|||||||
print(`Module ${info.path} could not be found`); disrupt
|
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 }
|
if (!used) { print(`Module ${info} returned null`); disrupt }
|
||||||
|
|
||||||
// stone(used)
|
|
||||||
return used
|
return used
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
61
test.ce
61
test.ce
@@ -331,14 +331,34 @@ function run_tests(package_name, specific_test) {
|
|||||||
var _test_error = null
|
var _test_error = null
|
||||||
var end_time = null
|
var end_time = null
|
||||||
var _run_one = 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)) {
|
if (is_function(test_mod)) {
|
||||||
push(tests, {name: 'main', fn: test_mod})
|
push(tests, {name: 'main', fn: test_mod})
|
||||||
} else if (is_object(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])) {
|
if (is_function(test_mod[k])) {
|
||||||
|
fn_count = fn_count + 1
|
||||||
push(tests, {name: k, fn: test_mod[k]})
|
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) {
|
if (length(tests) > 0) {
|
||||||
@@ -354,6 +374,7 @@ function run_tests(package_name, specific_test) {
|
|||||||
|
|
||||||
start_time = time.number()
|
start_time = time.number()
|
||||||
_test_error = null
|
_test_error = null
|
||||||
|
log.console(` RUN ${t.name}`)
|
||||||
_run_one = function() {
|
_run_one = function() {
|
||||||
var ret = t.fn()
|
var ret = t.fn()
|
||||||
|
|
||||||
@@ -367,8 +388,6 @@ function run_tests(package_name, specific_test) {
|
|||||||
|
|
||||||
test_entry.status = "passed"
|
test_entry.status = "passed"
|
||||||
log.console(` PASS ${t.name}`)
|
log.console(` PASS ${t.name}`)
|
||||||
pkg_result.passed++
|
|
||||||
file_result.passed++
|
|
||||||
} disruption {
|
} disruption {
|
||||||
var e = _test_error
|
var e = _test_error
|
||||||
test_entry.status = "failed"
|
test_entry.status = "failed"
|
||||||
@@ -386,16 +405,22 @@ function run_tests(package_name, specific_test) {
|
|||||||
if (test_entry.error.stack) {
|
if (test_entry.error.stack) {
|
||||||
log.console(` ${text(array(test_entry.error.stack, '\n'), '\n ')}`)
|
log.console(` ${text(array(test_entry.error.stack, '\n'), '\n ')}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
pkg_result.failed++
|
|
||||||
file_result.failed++
|
|
||||||
}
|
}
|
||||||
_run_one()
|
_run_one()
|
||||||
end_time = time.number()
|
end_time = time.number()
|
||||||
test_entry.duration_ns = round((end_time - start_time) * 1000000000)
|
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)
|
push(file_result.tests, test_entry)
|
||||||
pkg_result.total++
|
pkg_result.total = pkg_result.total + 1
|
||||||
if (gc_after_each_test) {
|
if (gc_after_each_test) {
|
||||||
dbg.gc()
|
dbg.gc()
|
||||||
}
|
}
|
||||||
@@ -591,22 +616,22 @@ function finalize_results() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
push(file_result.tests, r)
|
push(file_result.tests, r)
|
||||||
pkg_result.total++
|
pkg_result.total = pkg_result.total + 1
|
||||||
if (r.status == "passed") {
|
if (r.status == "passed") {
|
||||||
pkg_result.passed++
|
pkg_result.passed = pkg_result.passed + 1
|
||||||
file_result.passed++
|
file_result.passed = file_result.passed + 1
|
||||||
} else {
|
} else {
|
||||||
pkg_result.failed++
|
pkg_result.failed = pkg_result.failed + 1
|
||||||
file_result.failed++
|
file_result.failed = file_result.failed + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate totals
|
// Calculate totals
|
||||||
var totals = { total: 0, passed: 0, failed: 0 }
|
var totals = { total: 0, passed: 0, failed: 0 }
|
||||||
for (i = 0; i < length(all_results); i++) {
|
for (i = 0; i < length(all_results); i++) {
|
||||||
totals.total += all_results[i].total
|
totals.total = totals.total + all_results[i].total
|
||||||
totals.passed += all_results[i].passed
|
totals.passed = totals.passed + all_results[i].passed
|
||||||
totals.failed += all_results[i].failed
|
totals.failed = totals.failed + all_results[i].failed
|
||||||
}
|
}
|
||||||
|
|
||||||
log.console(`----------------------------------------`)
|
log.console(`----------------------------------------`)
|
||||||
@@ -621,9 +646,9 @@ var totals = null
|
|||||||
if (length(all_actor_tests) == 0) {
|
if (length(all_actor_tests) == 0) {
|
||||||
totals = { total: 0, passed: 0, failed: 0 }
|
totals = { total: 0, passed: 0, failed: 0 }
|
||||||
for (i = 0; i < length(all_results); i++) {
|
for (i = 0; i < length(all_results); i++) {
|
||||||
totals.total += all_results[i].total
|
totals.total = totals.total + all_results[i].total
|
||||||
totals.passed += all_results[i].passed
|
totals.passed = totals.passed + all_results[i].passed
|
||||||
totals.failed += all_results[i].failed
|
totals.failed = totals.failed + all_results[i].failed
|
||||||
}
|
}
|
||||||
|
|
||||||
log.console(`----------------------------------------`)
|
log.console(`----------------------------------------`)
|
||||||
|
|||||||
633
tests/suite.cm
633
tests/suite.cm
@@ -62,107 +62,117 @@ return {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// TYPE MIXING SHOULD THROW
|
// TYPE MIXING SHOULD DISRUPT
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test_number_plus_string_throws: function() {
|
test_number_plus_string_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = 1 + "hello"
|
var x = 1 + "hello"
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "number + string should throw"
|
_fn()
|
||||||
|
if (!caught) return "number + string should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_string_plus_number_throws: function() {
|
test_string_plus_number_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = "hello" + 1
|
var x = "hello" + 1
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "string + number should throw"
|
_fn()
|
||||||
|
if (!caught) return "string + number should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_object_plus_string_throws: function() {
|
test_object_plus_string_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = {} + "hello"
|
var x = {} + "hello"
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "object + string should throw"
|
_fn()
|
||||||
|
if (!caught) return "object + string should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_string_plus_object_throws: function() {
|
test_string_plus_object_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = "hello" + {}
|
var x = "hello" + {}
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "string + object should throw"
|
_fn()
|
||||||
|
if (!caught) return "string + object should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_plus_string_throws: function() {
|
test_array_plus_string_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = [] + "hello"
|
var x = [] + "hello"
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "array + string should throw"
|
_fn()
|
||||||
|
if (!caught) return "array + string should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_string_plus_array_throws: function() {
|
test_string_plus_array_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = "hello" + []
|
var x = "hello" + []
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "string + array should throw"
|
_fn()
|
||||||
|
if (!caught) return "string + array should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_boolean_plus_string_throws: function() {
|
test_boolean_plus_string_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = true + "hello"
|
var x = true + "hello"
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "boolean + string should throw"
|
_fn()
|
||||||
|
if (!caught) return "boolean + string should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_string_plus_boolean_throws: function() {
|
test_string_plus_boolean_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = "hello" + false
|
var x = "hello" + false
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "string + boolean should throw"
|
_fn()
|
||||||
|
if (!caught) return "string + boolean should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_null_plus_string_throws: function() {
|
test_null_plus_string_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = null + "hello"
|
var x = null + "hello"
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "null + string should throw"
|
_fn()
|
||||||
|
if (!caught) return "null + string should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_string_plus_null_throws: function() {
|
test_string_plus_null_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var x = "hello" + null
|
var x = "hello" + null
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "string + null should throw"
|
_fn()
|
||||||
|
if (!caught) return "string + null should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -314,102 +324,6 @@ return {
|
|||||||
if (x != 10) return "var reassignment failed"
|
if (x != 10) return "var reassignment failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// VAR BLOCK SCOPING (var now behaves like let)
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
test_var_block_scope_basic: function() {
|
|
||||||
var x = 1
|
|
||||||
{
|
|
||||||
var x = 2
|
|
||||||
if (x != 2) return "var should be block scoped - inner scope failed"
|
|
||||||
}
|
|
||||||
if (x != 1) return "var should be block scoped - outer scope affected"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_var_block_scope_if: function() {
|
|
||||||
var x = 1
|
|
||||||
if (true) {
|
|
||||||
var x = 2
|
|
||||||
if (x != 2) return "var in if block should be scoped"
|
|
||||||
}
|
|
||||||
if (x != 1) return "var in if block should not affect outer scope"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_var_block_scope_for: function() {
|
|
||||||
var x = 1
|
|
||||||
for (var i = 0; i < 1; i = i + 1) {
|
|
||||||
var x = 2
|
|
||||||
if (x != 2) return "var in for block should be scoped"
|
|
||||||
}
|
|
||||||
if (x != 1) return "var in for block should not affect outer scope"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_var_for_loop_iterator_scope: function() {
|
|
||||||
var sum = 0
|
|
||||||
for (var i = 0; i < 3; i = i + 1) {
|
|
||||||
sum = sum + i
|
|
||||||
}
|
|
||||||
if (sum != 3) return "for loop should work with block scoped var"
|
|
||||||
var caught = false
|
|
||||||
try {
|
|
||||||
var y = i
|
|
||||||
} catch (e) {
|
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "for loop iterator should not leak to outer scope"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_var_nested_blocks: function() {
|
|
||||||
var x = 1
|
|
||||||
{
|
|
||||||
var x = 2
|
|
||||||
{
|
|
||||||
var x = 3
|
|
||||||
if (x != 3) return "var in nested block level 2 failed"
|
|
||||||
}
|
|
||||||
if (x != 2) return "var in nested block level 1 failed"
|
|
||||||
}
|
|
||||||
if (x != 1) return "var in nested blocks outer scope failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_var_redeclaration_different_scope: function() {
|
|
||||||
var x = 1
|
|
||||||
{
|
|
||||||
var x = 2
|
|
||||||
}
|
|
||||||
if (x != 1) return "var in different scope should not affect outer"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_var_switch_scope: function() {
|
|
||||||
var x = 1
|
|
||||||
switch (1) {
|
|
||||||
case 1:
|
|
||||||
var x = 2
|
|
||||||
if (x != 2) return "var in switch should be block scoped"
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (x != 1) return "var in switch should not affect outer scope"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_var_while_scope: function() {
|
|
||||||
var x = 1
|
|
||||||
var count = 0
|
|
||||||
while (count < 1) {
|
|
||||||
var x = 2
|
|
||||||
if (x != 2) return "var in while should be block scoped"
|
|
||||||
count = count + 1
|
|
||||||
}
|
|
||||||
if (x != 1) return "var in while should not affect outer scope"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_var_no_initialization: function() {
|
|
||||||
{
|
|
||||||
var x
|
|
||||||
if (x != null) return "uninitialized var should be null"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
test_multiple_var_declaration: function() {
|
test_multiple_var_declaration: function() {
|
||||||
var a = 1, b = 2, c = 3
|
var a = 1, b = 2, c = 3
|
||||||
if (a != 1 || b != 2 || c != 3) return "multiple var declaration failed"
|
if (a != 1 || b != 2 || c != 3) return "multiple var declaration failed"
|
||||||
@@ -561,14 +475,14 @@ return {
|
|||||||
|
|
||||||
test_array_push: function() {
|
test_array_push: function() {
|
||||||
var arr = [1, 2]
|
var arr = [1, 2]
|
||||||
push(arr, 3)
|
arr[] = 3
|
||||||
if (length(arr) != 3) return "array push length failed"
|
if (length(arr) != 3) return "array push length failed"
|
||||||
if (arr[2] != 3) return "array push value failed"
|
if (arr[2] != 3) return "array push value failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_pop: function() {
|
test_array_pop: function() {
|
||||||
var arr = [1, 2, 3]
|
var arr = [1, 2, 3]
|
||||||
var val = pop(arr)
|
var val = arr[]
|
||||||
if (val != 3) return "array pop value failed"
|
if (val != 3) return "array pop value failed"
|
||||||
if (length(arr) != 2) return "array pop length failed"
|
if (length(arr) != 2) return "array pop length failed"
|
||||||
},
|
},
|
||||||
@@ -757,7 +671,8 @@ return {
|
|||||||
|
|
||||||
test_for_loop: function() {
|
test_for_loop: function() {
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (var i = 0; i < 5; i = i + 1) {
|
var i = 0
|
||||||
|
for (i = 0; i < 5; i = i + 1) {
|
||||||
sum = sum + i
|
sum = sum + i
|
||||||
}
|
}
|
||||||
if (sum != 10) return "for loop failed"
|
if (sum != 10) return "for loop failed"
|
||||||
@@ -765,7 +680,8 @@ return {
|
|||||||
|
|
||||||
test_for_loop_break: function() {
|
test_for_loop_break: function() {
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (var i = 0; i < 10; i = i + 1) {
|
var i = 0
|
||||||
|
for (i = 0; i < 10; i = i + 1) {
|
||||||
if (i == 5) break
|
if (i == 5) break
|
||||||
sum = sum + i
|
sum = sum + i
|
||||||
}
|
}
|
||||||
@@ -774,7 +690,8 @@ return {
|
|||||||
|
|
||||||
test_for_loop_continue: function() {
|
test_for_loop_continue: function() {
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (var i = 0; i < 10; i = i + 1) {
|
var i = 0
|
||||||
|
for (i = 0; i < 10; i = i + 1) {
|
||||||
if (i % 2 == 0) continue
|
if (i % 2 == 0) continue
|
||||||
sum = sum + i
|
sum = sum + i
|
||||||
}
|
}
|
||||||
@@ -783,8 +700,9 @@ return {
|
|||||||
|
|
||||||
test_nested_for_loops: function() {
|
test_nested_for_loops: function() {
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (var i = 0; i < 3; i = i + 1) {
|
var i = 0, j = 0
|
||||||
for (var j = 0; j < 3; j = j + 1) {
|
for (i = 0; i < 3; i = i + 1) {
|
||||||
|
for (j = 0; j < 3; j = j + 1) {
|
||||||
sum = sum + 1
|
sum = sum + 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -792,117 +710,62 @@ return {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// CONTROL FLOW - SWITCH
|
// DISRUPTION HANDLING
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test_switch_case: function() {
|
test_disruption_caught: function() {
|
||||||
var x = 2
|
|
||||||
var result = 0
|
|
||||||
switch (x) {
|
|
||||||
case 1:
|
|
||||||
result = 10
|
|
||||||
break
|
|
||||||
case 2:
|
|
||||||
result = 20
|
|
||||||
break
|
|
||||||
case 3:
|
|
||||||
result = 30
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (result != 20) return "switch case failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_switch_default: function() {
|
|
||||||
var x = 99
|
|
||||||
var result = 0
|
|
||||||
switch (x) {
|
|
||||||
case 1:
|
|
||||||
result = 10
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
result = -1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (result != -1) return "switch default failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_switch_fallthrough: function() {
|
|
||||||
var x = 1
|
|
||||||
var result = 0
|
|
||||||
switch (x) {
|
|
||||||
case 1:
|
|
||||||
result = result + 1
|
|
||||||
case 2:
|
|
||||||
result = result + 2
|
|
||||||
break
|
|
||||||
case 3:
|
|
||||||
result = result + 3
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if (result != 3) return "switch fallthrough failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// ERROR HANDLING - TRY/CATCH
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
test_try_catch: function() {
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
return "error"
|
disrupt
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "try catch failed"
|
_fn()
|
||||||
|
if (!caught) return "disruption not caught"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_try_catch_error_value: function() {
|
test_no_disruption_path: function() {
|
||||||
var errorMsg = null
|
|
||||||
try {
|
|
||||||
return "my error"
|
|
||||||
} catch (e) {
|
|
||||||
errorMsg = e
|
|
||||||
}
|
|
||||||
if (errorMsg != "my error") return "try catch error value failed"
|
|
||||||
},
|
|
||||||
|
|
||||||
test_try_no_error: function() {
|
|
||||||
var x = 0
|
var x = 0
|
||||||
try {
|
var _fn = function() {
|
||||||
x = 1
|
x = 1
|
||||||
} catch (e) {
|
} disruption {
|
||||||
x = 2
|
x = 2
|
||||||
}
|
}
|
||||||
if (x != 1) return "try no error failed"
|
_fn()
|
||||||
|
if (x != 1) return "non-disrupting code should not trigger disruption clause"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_nested_try_catch: function() {
|
test_nested_disruption: function() {
|
||||||
var x = 0
|
var x = 0
|
||||||
try {
|
var _outer = function() {
|
||||||
try {
|
var _inner = function() {
|
||||||
return "inner"
|
disrupt
|
||||||
} catch (e) {
|
} disruption {
|
||||||
x = 1
|
x = 1
|
||||||
}
|
}
|
||||||
|
_inner()
|
||||||
x = 2
|
x = 2
|
||||||
} catch (e) {
|
} disruption {
|
||||||
x = 3
|
x = 3
|
||||||
}
|
}
|
||||||
if (x != 2) return "nested try catch failed"
|
_outer()
|
||||||
|
if (x != 2) return "nested disruption failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_try_catch_rethrow: function() {
|
test_disruption_re_raise: function() {
|
||||||
var outerCaught = false
|
var outer_caught = false
|
||||||
try {
|
var _outer = function() {
|
||||||
try {
|
var _inner = function() {
|
||||||
return "error"
|
disrupt
|
||||||
} catch (e) {
|
} disruption {
|
||||||
return e
|
disrupt
|
||||||
}
|
}
|
||||||
} catch (e) {
|
_inner()
|
||||||
outerCaught = true
|
} disruption {
|
||||||
|
outer_caught = true
|
||||||
}
|
}
|
||||||
if (!outerCaught) return "try catch rereturn failed"
|
_outer()
|
||||||
|
if (!outer_caught) return "disruption re-raise failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -979,8 +842,8 @@ return {
|
|||||||
if (is_null("")) return "is_null empty string should be false"
|
if (is_null("")) return "is_null empty string should be false"
|
||||||
if (is_null({})) return "is_null object should be false"
|
if (is_null({})) return "is_null object should be false"
|
||||||
if (is_null([])) return "is_null array should be false"
|
if (is_null([])) return "is_null array should be false"
|
||||||
var x
|
var x = null
|
||||||
if (!is_null(x)) return "is_null undefined variable should be true"
|
if (!is_null(x)) return "is_null null variable should be true"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_is_blob: function() {
|
test_is_blob: function() {
|
||||||
@@ -1111,11 +974,12 @@ return {
|
|||||||
var obj = {x: 10}
|
var obj = {x: 10}
|
||||||
stone(obj)
|
stone(obj)
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
obj.x = 20
|
obj.x = 20
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
|
_fn()
|
||||||
if (!caught) return "stone object should prevent modification"
|
if (!caught) return "stone object should prevent modification"
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1130,11 +994,12 @@ return {
|
|||||||
var arr = [1, 2, 3]
|
var arr = [1, 2, 3]
|
||||||
stone(arr)
|
stone(arr)
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
arr[0] = 99
|
arr[0] = 99
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
|
_fn()
|
||||||
if (!caught) return "stone array should prevent modification"
|
if (!caught) return "stone array should prevent modification"
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -1382,24 +1247,25 @@ return {
|
|||||||
// NULL AND UNDEFINED BEHAVIOR
|
// NULL AND UNDEFINED BEHAVIOR
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test_undefined_variable_is_null: function() {
|
test_null_initialized_variable: function() {
|
||||||
var x
|
var x = null
|
||||||
if (x != null) return "undefined variable should be null"
|
if (x != null) return "null initialized variable should be null"
|
||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// NUMBERS - SPECIAL OPERATIONS
|
// NUMBERS - SPECIAL OPERATIONS
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test_number_toString_implicit: function() {
|
test_number_plus_empty_string_disrupts: function() {
|
||||||
var n = 42
|
var n = 42
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() {
|
||||||
var result = n + ""
|
var result = n + ""
|
||||||
} catch (e) {
|
} disruption {
|
||||||
caught = true
|
caught = true
|
||||||
}
|
}
|
||||||
if (!caught) return "number + string should throw"
|
_fn()
|
||||||
|
if (!caught) return "number + string should disrupt"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_number_division_by_zero: function() {
|
test_number_division_by_zero: function() {
|
||||||
@@ -1498,14 +1364,11 @@ return {
|
|||||||
if (str != "a,b,c") return "array join with text() failed"
|
if (str != "a,b,c") return "array join with text() failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_text_array_join_numbers_throw: function() {
|
test_text_array_join_numbers_disrupts: function() {
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { text([1, 2, 3], ",") } disruption { caught = true }
|
||||||
text([1, 2, 3], ",")
|
_fn()
|
||||||
} catch (e) {
|
if (!caught) return "text([numbers], sep) should disrupt (no implicit coercion)"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "text([numbers], sep) should return (no implicit coercion)"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_text_array_join_numbers_explicit: function() {
|
test_text_array_join_numbers_explicit: function() {
|
||||||
@@ -1675,110 +1538,71 @@ return {
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_string_key_throws: function() {
|
test_array_string_key_disrupts: function() {
|
||||||
var a = []
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = []; a["a"] = 1 } disruption { caught = true }
|
||||||
a["a"] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "array should not use string as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "array should not be able to use string as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_object_key_throws: function() {
|
test_array_object_key_disrupts: function() {
|
||||||
var a = []
|
|
||||||
var b = {}
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = []; var b = {}; a[b] = 1 } disruption { caught = true }
|
||||||
a[b] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "array should not use object as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "array should not be able to use object as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_boolean_key_throws: function() {
|
test_array_boolean_key_disrupts: function() {
|
||||||
var a = []
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = []; a[true] = 1 } disruption { caught = true }
|
||||||
a[true] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "array should not use boolean as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "array should not be able to use boolean as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_null_key_throws: function() {
|
test_array_null_key_disrupts: function() {
|
||||||
var a = []
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = []; a[null] = 1 } disruption { caught = true }
|
||||||
a[null] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "array should not use null as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "array should not be able to use null as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_array_array_key_throws: function() {
|
test_array_array_key_disrupts: function() {
|
||||||
var a = []
|
|
||||||
var c = []
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = []; var c = []; a[c] = 1 } disruption { caught = true }
|
||||||
a[c] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "array should not use array as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "array should not be able to use array as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_obj_number_key_throws: function() {
|
test_obj_number_key_disrupts: function() {
|
||||||
var a = {}
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = {}; a[1] = 1 } disruption { caught = true }
|
||||||
a[1] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "object should not use number as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "object should not be able to use number as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_obj_array_key_throws: function() {
|
test_obj_array_key_disrupts: function() {
|
||||||
var a = {}
|
|
||||||
var c = []
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = {}; var c = []; a[c] = 1 } disruption { caught = true }
|
||||||
a[c] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "object should not use array as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "object should not be able to use array as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_obj_boolean_key_throws: function() {
|
test_obj_boolean_key_disrupts: function() {
|
||||||
var a = {}
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = {}; a[true] = 1 } disruption { caught = true }
|
||||||
a[true] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "object should not use boolean as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "object should not be able to use boolean as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_obj_null_key_throws: function() {
|
test_obj_null_key_disrupts: function() {
|
||||||
var a = {}
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var a = {}; a[null] = 1 } disruption { caught = true }
|
||||||
a[null] = 1
|
_fn()
|
||||||
} catch(e) {
|
if (!caught) return "object should not use null as key"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "object should not be able to use null as key"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// RETRIEVAL WITH INVALID KEY RETURNS NULL (not throw)
|
// RETRIEVAL WITH INVALID KEY RETURNS NULL (not disrupt)
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test_array_get_string_key_returns_null: function() {
|
test_array_get_string_key_returns_null: function() {
|
||||||
@@ -1852,26 +1676,18 @@ return {
|
|||||||
if (arity != 2) return "length of function should return its arity"
|
if (arity != 2) return "length of function should return its arity"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_function_property_set_throws: function() {
|
test_function_property_set_disrupts: function() {
|
||||||
var fn = function() {}
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var fn = function() {}; fn.foo = 123 } disruption { caught = true }
|
||||||
fn.foo = 123
|
_fn()
|
||||||
} catch (e) {
|
if (!caught) return "setting property on function should disrupt"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "setting property on function should throw"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_function_bracket_access_throws: function() {
|
test_function_bracket_access_disrupts: function() {
|
||||||
var fn = function() {}
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var fn = function() {}; var x = fn["length"]() } disruption { caught = true }
|
||||||
var x = fn["length"]()
|
_fn()
|
||||||
} catch (e) {
|
if (!caught) return "bracket access on function should disrupt"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "bracket access on function should throw"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_length_returns_function_arity: function() {
|
test_length_returns_function_arity: function() {
|
||||||
@@ -1941,7 +1757,8 @@ return {
|
|||||||
test_function_proxy_with_multiple_args: function() {
|
test_function_proxy_with_multiple_args: function() {
|
||||||
var proxy = function(name, args) {
|
var proxy = function(name, args) {
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (var i = 0; i < length(args); i++) {
|
var i = 0
|
||||||
|
for (i = 0; i < length(args); i++) {
|
||||||
sum = sum + args[i]
|
sum = sum + args[i]
|
||||||
}
|
}
|
||||||
return `${name}:${sum}`
|
return `${name}:${sum}`
|
||||||
@@ -1988,18 +1805,14 @@ return {
|
|||||||
if (proxy.add(3, 4) != 7) return "proxy dispatch add failed"
|
if (proxy.add(3, 4) != 7) return "proxy dispatch add failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_function_proxy_unknown_method_throws: function() {
|
test_function_proxy_unknown_method_disrupts: function() {
|
||||||
var proxy = function(name, args) {
|
var proxy = function(name, args) {
|
||||||
return `no such method: ${name}`
|
disrupt
|
||||||
}
|
}
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { proxy.nonexistent() } disruption { caught = true }
|
||||||
proxy.nonexistent()
|
_fn()
|
||||||
} catch (e) {
|
if (!caught) return "proxy should disrupt for unknown method"
|
||||||
caught = true
|
|
||||||
if (search(e, "no such method") == null) return "wrong error message"
|
|
||||||
}
|
|
||||||
if (!caught) return "proxy should return for unknown method"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_function_proxy_is_function: function() {
|
test_function_proxy_is_function: function() {
|
||||||
@@ -2016,15 +1829,11 @@ return {
|
|||||||
if (length(proxy) != 2) return "proxy function should have length 2"
|
if (length(proxy) != 2) return "proxy function should have length 2"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_function_proxy_property_read_still_throws: function() {
|
test_function_proxy_property_read_disrupts: function() {
|
||||||
var fn = function() { return 1 }
|
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var fn = function() { return 1 }; var x = fn.someProp } disruption { caught = true }
|
||||||
var x = fn.someProp
|
_fn()
|
||||||
} catch (e) {
|
if (!caught) return "reading property from non-proxy function should disrupt"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "reading property from function (not method call) should throw"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_function_proxy_nested_calls: function() {
|
test_function_proxy_nested_calls: function() {
|
||||||
@@ -2071,8 +1880,8 @@ return {
|
|||||||
|
|
||||||
test_function_proxy_args_array_is_real_array: function() {
|
test_function_proxy_args_array_is_real_array: function() {
|
||||||
var proxy = function(name, args) {
|
var proxy = function(name, args) {
|
||||||
if (!is_array(args)) return "args should be array"
|
if (!is_array(args)) disrupt
|
||||||
push(args, 4)
|
args[] = 4
|
||||||
return length(args)
|
return length(args)
|
||||||
}
|
}
|
||||||
var result = proxy.test(1, 2, 3)
|
var result = proxy.test(1, 2, 3)
|
||||||
@@ -2087,17 +1896,14 @@ return {
|
|||||||
if (result != null) return "proxy should have null this"
|
if (result != null) return "proxy should have null this"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_function_proxy_integer_bracket_key: function() {
|
test_function_proxy_integer_bracket_key_disrupts: function() {
|
||||||
var proxy = function(name, args) {
|
var proxy = function(name, args) {
|
||||||
return `key:${name}`
|
return `key:${name}`
|
||||||
}
|
}
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { var result = proxy[42]() } disruption { caught = true }
|
||||||
var result = proxy[42]()
|
_fn()
|
||||||
} catch (e) {
|
if (!caught) return "proxy with integer bracket key should disrupt"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "proxy with integer bracket key should throw"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -3188,15 +2994,12 @@ return {
|
|||||||
if (obj.b != 2) return "delete should not affect other properties"
|
if (obj.b != 2) return "delete should not affect other properties"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_delete_array_element: function() {
|
test_delete_array_element_disrupts: function() {
|
||||||
var arr = [1, 2, 3]
|
var arr = [1, 2, 3]
|
||||||
var caught = false
|
var caught = false
|
||||||
try {
|
var _fn = function() { delete arr[1] } disruption { caught = true }
|
||||||
delete arr[1]
|
_fn()
|
||||||
} catch (e) {
|
if (!caught) return "delete on array element should disrupt"
|
||||||
caught = true
|
|
||||||
}
|
|
||||||
if (!caught) return "delete on array element should throw"
|
|
||||||
},
|
},
|
||||||
|
|
||||||
test_delete_nonexistent: function() {
|
test_delete_nonexistent: function() {
|
||||||
@@ -3247,22 +3050,21 @@ return {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// ERROR OBJECTS
|
// DISRUPTION IN EXPRESSIONS
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test_error_creation: function() {
|
test_disruption_in_nested_function: function() {
|
||||||
var e = Error("test message")
|
var caught = false
|
||||||
if (e.message != "test message") return "Error creation failed"
|
var _outer = function() {
|
||||||
},
|
var _inner = function() {
|
||||||
|
disrupt
|
||||||
test_throw_error_object: function() {
|
} disruption {
|
||||||
var caught = null
|
caught = true
|
||||||
try {
|
}
|
||||||
return Error("my error")
|
_inner()
|
||||||
} catch (e) {
|
|
||||||
caught = e
|
|
||||||
}
|
}
|
||||||
if (!caught || caught.message != "my error") return "return Error object failed"
|
_outer()
|
||||||
|
if (!caught) return "disruption in nested function failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -3487,8 +3289,9 @@ return {
|
|||||||
|
|
||||||
test_gc_cycle_array_self: function() {
|
test_gc_cycle_array_self: function() {
|
||||||
var arr = []
|
var arr = []
|
||||||
for (var i = 0; i < 10; i++) {
|
var i = 0
|
||||||
push(arr, arr)
|
for (i = 0; i < 10; i++) {
|
||||||
|
arr[] = arr
|
||||||
}
|
}
|
||||||
if (arr[0] != arr) return "array self cycle failed"
|
if (arr[0] != arr) return "array self cycle failed"
|
||||||
},
|
},
|
||||||
@@ -3589,9 +3392,8 @@ return {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test_splat_prototype_flattening: function() {
|
test_splat_prototype_flattening: function() {
|
||||||
var proto = {x: 10, y: 20}
|
var proto_obj = {x: 10, y: 20}
|
||||||
var obj = {z: 30}
|
var obj = meme(proto_obj, {z: 30})
|
||||||
obj.__proto__ = proto
|
|
||||||
var flat = splat(obj)
|
var flat = splat(obj)
|
||||||
if (flat.x != 10) return "splat x failed"
|
if (flat.x != 10) return "splat x failed"
|
||||||
if (flat.y != 20) return "splat y failed"
|
if (flat.y != 20) return "splat y failed"
|
||||||
@@ -3618,20 +3420,20 @@ return {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
test_apply_with_array_args: function() {
|
test_apply_with_array_args: function() {
|
||||||
def sum = function(a, b, c) { return a + b + c }
|
var sum = function(a, b, c) { return a + b + c }
|
||||||
var result = fn.apply(sum, [1, 2, 3])
|
var result = apply(sum, [1, 2, 3])
|
||||||
if (result != 6) return "apply with array args failed"
|
if (result != 6) return "apply with array args failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_apply_with_no_args: function() {
|
test_apply_with_no_args: function() {
|
||||||
def ret42 = function() { return 42 }
|
var ret42 = function() { return 42 }
|
||||||
var result = fn.apply(ret42)
|
var result = apply(ret42, [])
|
||||||
if (result != 42) return "apply with no args failed"
|
if (result != 42) return "apply with no args failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
test_apply_with_single_value: function() {
|
test_apply_with_single_value: function() {
|
||||||
def double = function(x) { return x * 2 }
|
var double = function(x) { return x * 2 }
|
||||||
var result = fn.apply(double, 10)
|
var result = apply(double, [10])
|
||||||
if (result != 20) return "apply with single value failed"
|
if (result != 20) return "apply with single value failed"
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -3642,12 +3444,14 @@ return {
|
|||||||
test_gc_reverse_under_pressure: function() {
|
test_gc_reverse_under_pressure: function() {
|
||||||
// Create GC pressure by making many arrays, then reverse
|
// Create GC pressure by making many arrays, then reverse
|
||||||
var arrays = []
|
var arrays = []
|
||||||
for (var i = 0; i < 100; i = i + 1) {
|
var i = 0
|
||||||
|
var rev = null
|
||||||
|
for (i = 0; i < 100; i = i + 1) {
|
||||||
arrays[i] = [i, i+1, i+2, i+3, i+4]
|
arrays[i] = [i, i+1, i+2, i+3, i+4]
|
||||||
}
|
}
|
||||||
// Now reverse each one - this tests re-chase after allocation
|
// Now reverse each one - this tests re-chase after allocation
|
||||||
for (var i = 0; i < 100; i = i + 1) {
|
for (i = 0; i < 100; i = i + 1) {
|
||||||
var rev = reverse(arrays[i])
|
rev = reverse(arrays[i])
|
||||||
if (rev[0] != i+4) return "gc reverse stress failed at " + text(i)
|
if (rev[0] != i+4) return "gc reverse stress failed at " + text(i)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -3655,12 +3459,14 @@ return {
|
|||||||
test_gc_object_select_under_pressure: function() {
|
test_gc_object_select_under_pressure: function() {
|
||||||
// Create GC pressure
|
// Create GC pressure
|
||||||
var objs = []
|
var objs = []
|
||||||
for (var i = 0; i < 100; i = i + 1) {
|
var i = 0
|
||||||
|
var selected = null
|
||||||
|
for (i = 0; i < 100; i = i + 1) {
|
||||||
objs[i] = {a: i, b: i+1, c: i+2, d: i+3}
|
objs[i] = {a: i, b: i+1, c: i+2, d: i+3}
|
||||||
}
|
}
|
||||||
// Select keys - tests re-chase in loop
|
// Select keys - tests re-chase in loop
|
||||||
for (var i = 0; i < 100; i = i + 1) {
|
for (i = 0; i < 100; i = i + 1) {
|
||||||
var selected = object(objs[i], ["a", "c"])
|
selected = object(objs[i], ["a", "c"])
|
||||||
if (selected.a != i) return "gc object select stress failed at " + text(i)
|
if (selected.a != i) return "gc object select stress failed at " + text(i)
|
||||||
if (selected.c != i+2) return "gc object select stress c failed at " + text(i)
|
if (selected.c != i+2) return "gc object select stress c failed at " + text(i)
|
||||||
}
|
}
|
||||||
@@ -3669,13 +3475,16 @@ return {
|
|||||||
test_gc_object_from_keys_function_under_pressure: function() {
|
test_gc_object_from_keys_function_under_pressure: function() {
|
||||||
// Create GC pressure
|
// Create GC pressure
|
||||||
var keysets = []
|
var keysets = []
|
||||||
for (var i = 0; i < 50; i = i + 1) {
|
var i = 0
|
||||||
|
var obj = null
|
||||||
|
var expected = null
|
||||||
|
for (i = 0; i < 50; i = i + 1) {
|
||||||
keysets[i] = ["k" + text(i), "j" + text(i), "m" + text(i)]
|
keysets[i] = ["k" + text(i), "j" + text(i), "m" + text(i)]
|
||||||
}
|
}
|
||||||
// Create objects with function - tests JS_PUSH/POP and re-chase
|
// Create objects with function - tests JS_PUSH/POP and re-chase
|
||||||
for (var i = 0; i < 50; i = i + 1) {
|
for (i = 0; i < 50; i = i + 1) {
|
||||||
var obj = object(keysets[i], function(k) { return k + "_value" })
|
obj = object(keysets[i], function(k) { return k + "_value" })
|
||||||
var expected = "k" + text(i) + "_value"
|
expected = "k" + text(i) + "_value"
|
||||||
if (obj["k" + text(i)] != expected) return "gc object from keys func stress failed at " + text(i)
|
if (obj["k" + text(i)] != expected) return "gc object from keys func stress failed at " + text(i)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
459
vm_suite.ce
459
vm_suite.ce
@@ -4262,6 +4262,465 @@ run("IIFE with arguments", function() {
|
|||||||
assert_eq(result, 30, "IIFE sum")
|
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
|
// SUMMARY
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
Reference in New Issue
Block a user