add object literal test

This commit is contained in:
2026-02-10 17:28:59 -06:00
parent fe5dc6ecc9
commit ddf3fc1c77
5 changed files with 761 additions and 515 deletions

View File

@@ -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
try {
var _fn = function() {
var x = 1 + "hello"
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = "hello" + 1
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = {} + "hello"
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = "hello" + {}
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = [] + "hello"
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = "hello" + []
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = true + "hello"
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = "hello" + false
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = null + "hello"
} catch (e) {
} disruption {
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
try {
var _fn = function() {
var x = "hello" + null
} catch (e) {
} disruption {
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"
},
// ============================================================================
// 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() {
var a = 1, b = 2, c = 3
if (a != 1 || b != 2 || c != 3) return "multiple var declaration failed"
@@ -561,14 +475,14 @@ return {
test_array_push: function() {
var arr = [1, 2]
push(arr, 3)
arr[] = 3
if (length(arr) != 3) return "array push length failed"
if (arr[2] != 3) return "array push value failed"
},
test_array_pop: function() {
var arr = [1, 2, 3]
var val = pop(arr)
var val = arr[]
if (val != 3) return "array pop value failed"
if (length(arr) != 2) return "array pop length failed"
},
@@ -757,7 +671,8 @@ return {
test_for_loop: function() {
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
}
if (sum != 10) return "for loop failed"
@@ -765,7 +680,8 @@ return {
test_for_loop_break: function() {
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
sum = sum + i
}
@@ -774,7 +690,8 @@ return {
test_for_loop_continue: function() {
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
sum = sum + i
}
@@ -783,8 +700,9 @@ return {
test_nested_for_loops: function() {
var sum = 0
for (var i = 0; i < 3; i = i + 1) {
for (var j = 0; j < 3; j = j + 1) {
var i = 0, j = 0
for (i = 0; i < 3; i = i + 1) {
for (j = 0; j < 3; j = j + 1) {
sum = sum + 1
}
}
@@ -792,117 +710,62 @@ return {
},
// ============================================================================
// CONTROL FLOW - SWITCH
// DISRUPTION HANDLING
// ============================================================================
test_switch_case: 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() {
test_disruption_caught: function() {
var caught = false
try {
return "error"
} catch (e) {
var _fn = function() {
disrupt
} disruption {
caught = true
}
if (!caught) return "try catch failed"
_fn()
if (!caught) return "disruption not caught"
},
test_try_catch_error_value: 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() {
test_no_disruption_path: function() {
var x = 0
try {
var _fn = function() {
x = 1
} catch (e) {
} disruption {
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
try {
try {
return "inner"
} catch (e) {
var _outer = function() {
var _inner = function() {
disrupt
} disruption {
x = 1
}
_inner()
x = 2
} catch (e) {
} disruption {
x = 3
}
if (x != 2) return "nested try catch failed"
_outer()
if (x != 2) return "nested disruption failed"
},
test_try_catch_rethrow: function() {
var outerCaught = false
try {
try {
return "error"
} catch (e) {
return e
test_disruption_re_raise: function() {
var outer_caught = false
var _outer = function() {
var _inner = function() {
disrupt
} disruption {
disrupt
}
} catch (e) {
outerCaught = true
_inner()
} 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 object should be false"
if (is_null([])) return "is_null array should be false"
var x
if (!is_null(x)) return "is_null undefined variable should be true"
var x = null
if (!is_null(x)) return "is_null null variable should be true"
},
test_is_blob: function() {
@@ -1111,11 +974,12 @@ return {
var obj = {x: 10}
stone(obj)
var caught = false
try {
var _fn = function() {
obj.x = 20
} catch (e) {
} disruption {
caught = true
}
_fn()
if (!caught) return "stone object should prevent modification"
},
@@ -1130,11 +994,12 @@ return {
var arr = [1, 2, 3]
stone(arr)
var caught = false
try {
var _fn = function() {
arr[0] = 99
} catch (e) {
} disruption {
caught = true
}
_fn()
if (!caught) return "stone array should prevent modification"
},
@@ -1382,24 +1247,25 @@ return {
// NULL AND UNDEFINED BEHAVIOR
// ============================================================================
test_undefined_variable_is_null: function() {
var x
if (x != null) return "undefined variable should be null"
test_null_initialized_variable: function() {
var x = null
if (x != null) return "null initialized variable should be null"
},
// ============================================================================
// NUMBERS - SPECIAL OPERATIONS
// ============================================================================
test_number_toString_implicit: function() {
test_number_plus_empty_string_disrupts: function() {
var n = 42
var caught = false
try {
var _fn = function() {
var result = n + ""
} catch (e) {
} disruption {
caught = true
}
if (!caught) return "number + string should throw"
_fn()
if (!caught) return "number + string should disrupt"
},
test_number_division_by_zero: function() {
@@ -1498,14 +1364,11 @@ return {
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
try {
text([1, 2, 3], ",")
} catch (e) {
caught = true
}
if (!caught) return "text([numbers], sep) should return (no implicit coercion)"
var _fn = function() { text([1, 2, 3], ",") } disruption { caught = true }
_fn()
if (!caught) return "text([numbers], sep) should disrupt (no implicit coercion)"
},
test_text_array_join_numbers_explicit: function() {
@@ -1675,110 +1538,71 @@ return {
})
},
test_array_string_key_throws: function() {
var a = []
test_array_string_key_disrupts: function() {
var caught = false
try {
a["a"] = 1
} catch(e) {
caught = true
}
if (!caught) return "array should not be able to use string as key"
var _fn = function() { var a = []; a["a"] = 1 } disruption { caught = true }
_fn()
if (!caught) return "array should not use string as key"
},
test_array_object_key_throws: function() {
var a = []
var b = {}
test_array_object_key_disrupts: function() {
var caught = false
try {
a[b] = 1
} catch(e) {
caught = true
}
if (!caught) return "array should not be able to use object as key"
var _fn = function() { var a = []; var b = {}; a[b] = 1 } disruption { caught = true }
_fn()
if (!caught) return "array should not use object as key"
},
test_array_boolean_key_throws: function() {
var a = []
test_array_boolean_key_disrupts: function() {
var caught = false
try {
a[true] = 1
} catch(e) {
caught = true
}
if (!caught) return "array should not be able to use boolean as key"
var _fn = function() { var a = []; a[true] = 1 } disruption { caught = true }
_fn()
if (!caught) return "array should not use boolean as key"
},
test_array_null_key_throws: function() {
var a = []
test_array_null_key_disrupts: function() {
var caught = false
try {
a[null] = 1
} catch(e) {
caught = true
}
if (!caught) return "array should not be able to use null as key"
var _fn = function() { var a = []; a[null] = 1 } disruption { caught = true }
_fn()
if (!caught) return "array should not use null as key"
},
test_array_array_key_throws: function() {
var a = []
var c = []
test_array_array_key_disrupts: function() {
var caught = false
try {
a[c] = 1
} catch(e) {
caught = true
}
if (!caught) return "array should not be able to use array as key"
var _fn = function() { var a = []; var c = []; a[c] = 1 } disruption { caught = true }
_fn()
if (!caught) return "array should not use array as key"
},
test_obj_number_key_throws: function() {
var a = {}
test_obj_number_key_disrupts: function() {
var caught = false
try {
a[1] = 1
} catch(e) {
caught = true
}
if (!caught) return "object should not be able to use number as key"
var _fn = function() { var a = {}; a[1] = 1 } disruption { caught = true }
_fn()
if (!caught) return "object should not use number as key"
},
test_obj_array_key_throws: function() {
var a = {}
var c = []
test_obj_array_key_disrupts: function() {
var caught = false
try {
a[c] = 1
} catch(e) {
caught = true
}
if (!caught) return "object should not be able to use array as key"
var _fn = function() { var a = {}; var c = []; a[c] = 1 } disruption { caught = true }
_fn()
if (!caught) return "object should not use array as key"
},
test_obj_boolean_key_throws: function() {
var a = {}
test_obj_boolean_key_disrupts: function() {
var caught = false
try {
a[true] = 1
} catch(e) {
caught = true
}
if (!caught) return "object should not be able to use boolean as key"
var _fn = function() { var a = {}; a[true] = 1 } disruption { caught = true }
_fn()
if (!caught) return "object should not use boolean as key"
},
test_obj_null_key_throws: function() {
var a = {}
test_obj_null_key_disrupts: function() {
var caught = false
try {
a[null] = 1
} catch(e) {
caught = true
}
if (!caught) return "object should not be able to use null as key"
var _fn = function() { var a = {}; a[null] = 1 } disruption { caught = true }
_fn()
if (!caught) return "object should not 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() {
@@ -1852,26 +1676,18 @@ return {
if (arity != 2) return "length of function should return its arity"
},
test_function_property_set_throws: function() {
var fn = function() {}
test_function_property_set_disrupts: function() {
var caught = false
try {
fn.foo = 123
} catch (e) {
caught = true
}
if (!caught) return "setting property on function should throw"
var _fn = function() { var fn = function() {}; fn.foo = 123 } disruption { caught = true }
_fn()
if (!caught) return "setting property on function should disrupt"
},
test_function_bracket_access_throws: function() {
var fn = function() {}
test_function_bracket_access_disrupts: function() {
var caught = false
try {
var x = fn["length"]()
} catch (e) {
caught = true
}
if (!caught) return "bracket access on function should throw"
var _fn = function() { var fn = function() {}; var x = fn["length"]() } disruption { caught = true }
_fn()
if (!caught) return "bracket access on function should disrupt"
},
test_length_returns_function_arity: function() {
@@ -1941,7 +1757,8 @@ return {
test_function_proxy_with_multiple_args: function() {
var proxy = function(name, args) {
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]
}
return `${name}:${sum}`
@@ -1988,18 +1805,14 @@ return {
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) {
return `no such method: ${name}`
disrupt
}
var caught = false
try {
proxy.nonexistent()
} catch (e) {
caught = true
if (search(e, "no such method") == null) return "wrong error message"
}
if (!caught) return "proxy should return for unknown method"
var _fn = function() { proxy.nonexistent() } disruption { caught = true }
_fn()
if (!caught) return "proxy should disrupt for unknown method"
},
test_function_proxy_is_function: function() {
@@ -2016,15 +1829,11 @@ return {
if (length(proxy) != 2) return "proxy function should have length 2"
},
test_function_proxy_property_read_still_throws: function() {
var fn = function() { return 1 }
test_function_proxy_property_read_disrupts: function() {
var caught = false
try {
var x = fn.someProp
} catch (e) {
caught = true
}
if (!caught) return "reading property from function (not method call) should throw"
var _fn = function() { var fn = function() { return 1 }; var x = fn.someProp } disruption { caught = true }
_fn()
if (!caught) return "reading property from non-proxy function should disrupt"
},
test_function_proxy_nested_calls: function() {
@@ -2071,8 +1880,8 @@ return {
test_function_proxy_args_array_is_real_array: function() {
var proxy = function(name, args) {
if (!is_array(args)) return "args should be array"
push(args, 4)
if (!is_array(args)) disrupt
args[] = 4
return length(args)
}
var result = proxy.test(1, 2, 3)
@@ -2087,17 +1896,14 @@ return {
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) {
return `key:${name}`
}
var caught = false
try {
var result = proxy[42]()
} catch (e) {
caught = true
}
if (!caught) return "proxy with integer bracket key should throw"
var _fn = function() { var result = proxy[42]() } disruption { caught = true }
_fn()
if (!caught) return "proxy with integer bracket key should disrupt"
},
// ============================================================================
@@ -3188,15 +2994,12 @@ return {
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 caught = false
try {
delete arr[1]
} catch (e) {
caught = true
}
if (!caught) return "delete on array element should throw"
var _fn = function() { delete arr[1] } disruption { caught = true }
_fn()
if (!caught) return "delete on array element should disrupt"
},
test_delete_nonexistent: function() {
@@ -3247,22 +3050,21 @@ return {
},
// ============================================================================
// ERROR OBJECTS
// DISRUPTION IN EXPRESSIONS
// ============================================================================
test_error_creation: function() {
var e = Error("test message")
if (e.message != "test message") return "Error creation failed"
},
test_throw_error_object: function() {
var caught = null
try {
return Error("my error")
} catch (e) {
caught = e
test_disruption_in_nested_function: function() {
var caught = false
var _outer = function() {
var _inner = function() {
disrupt
} disruption {
caught = true
}
_inner()
}
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() {
var arr = []
for (var i = 0; i < 10; i++) {
push(arr, arr)
var i = 0
for (i = 0; i < 10; i++) {
arr[] = arr
}
if (arr[0] != arr) return "array self cycle failed"
},
@@ -3589,9 +3392,8 @@ return {
// ============================================================================
test_splat_prototype_flattening: function() {
var proto = {x: 10, y: 20}
var obj = {z: 30}
obj.__proto__ = proto
var proto_obj = {x: 10, y: 20}
var obj = meme(proto_obj, {z: 30})
var flat = splat(obj)
if (flat.x != 10) return "splat x failed"
if (flat.y != 20) return "splat y failed"
@@ -3618,20 +3420,20 @@ return {
// ============================================================================
test_apply_with_array_args: function() {
def sum = function(a, b, c) { return a + b + c }
var result = fn.apply(sum, [1, 2, 3])
var sum = function(a, b, c) { return a + b + c }
var result = apply(sum, [1, 2, 3])
if (result != 6) return "apply with array args failed"
},
test_apply_with_no_args: function() {
def ret42 = function() { return 42 }
var result = fn.apply(ret42)
var ret42 = function() { return 42 }
var result = apply(ret42, [])
if (result != 42) return "apply with no args failed"
},
test_apply_with_single_value: function() {
def double = function(x) { return x * 2 }
var result = fn.apply(double, 10)
var double = function(x) { return x * 2 }
var result = apply(double, [10])
if (result != 20) return "apply with single value failed"
},
@@ -3642,12 +3444,14 @@ return {
test_gc_reverse_under_pressure: function() {
// Create GC pressure by making many arrays, then reverse
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]
}
// Now reverse each one - this tests re-chase after allocation
for (var i = 0; i < 100; i = i + 1) {
var rev = reverse(arrays[i])
for (i = 0; i < 100; i = i + 1) {
rev = reverse(arrays[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() {
// Create GC pressure
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}
}
// Select keys - tests re-chase in loop
for (var i = 0; i < 100; i = i + 1) {
var selected = object(objs[i], ["a", "c"])
for (i = 0; i < 100; i = i + 1) {
selected = object(objs[i], ["a", "c"])
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)
}
@@ -3669,13 +3475,16 @@ return {
test_gc_object_from_keys_function_under_pressure: function() {
// Create GC pressure
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)]
}
// Create objects with function - tests JS_PUSH/POP and re-chase
for (var i = 0; i < 50; i = i + 1) {
var obj = object(keysets[i], function(k) { return k + "_value" })
var expected = "k" + text(i) + "_value"
for (i = 0; i < 50; i = i + 1) {
obj = object(keysets[i], function(k) { return k + "_value" })
expected = "k" + text(i) + "_value"
if (obj["k" + text(i)] != expected) return "gc object from keys func stress failed at " + text(i)
}
},