add object literal test
This commit is contained in:
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
|
||||
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)
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user