diff --git a/error_test.go b/error_test.go index 87e8f6f..0364147 100644 --- a/error_test.go +++ b/error_test.go @@ -9,6 +9,7 @@ func TestError(t *testing.T) { Terst(t) test := runTest() + test(` [ Error.prototype.name, Error.prototype.message, Error.prototype.hasOwnProperty("message") ]; `, "Error,,true") @@ -18,9 +19,8 @@ func TestError_instanceof(t *testing.T) { Terst(t) test := runTest() - test(` - (new TypeError()) instanceof Error - `, "true") + + test(`(new TypeError()) instanceof Error`, true) } func TestPanicValue(t *testing.T) { @@ -33,6 +33,7 @@ func TestPanicValue(t *testing.T) { Is(err, nil) panic(value) }) + test(` try { abc(); @@ -47,10 +48,8 @@ func TestPanicValue(t *testing.T) { func Test_catchPanic(t *testing.T) { Terst(t) - // TODO This is here because ToValue(nil) was failing - return - otto, _ := runTestWithOtto() + _, err := otto.Run(` A syntax error that does not define diff --git a/function_test.go b/function_test.go index bc94e3f..4739156 100644 --- a/function_test.go +++ b/function_test.go @@ -9,6 +9,7 @@ func TestFunction(t *testing.T) { Terst(t) test := runTest() + test(` var abc = Object.getOwnPropertyDescriptor(Function, "prototype"); [ [ typeof Function.prototype, typeof Function.prototype.length, Function.prototype.length ], @@ -26,6 +27,7 @@ func TestFunction_new(t *testing.T) { Terst(t) test := runTest() + test(`raise: new Function({}); `, "SyntaxError: Unexpected identifier") @@ -68,7 +70,8 @@ func TestFunction_apply(t *testing.T) { Terst(t) test := runTest() - test(`Function.prototype.apply.length`, "2") + + test(`Function.prototype.apply.length`, 2) test(`String.prototype.substring.apply("abc", [1, 11])`, "bc") } @@ -76,7 +79,8 @@ func TestFunction_call(t *testing.T) { Terst(t) test := runTest() - test(`Function.prototype.call.length`, "1") + + test(`Function.prototype.call.length`, 1) test(`String.prototype.substring.call("abc", 1, 11)`, "bc") } @@ -84,6 +88,7 @@ func TestFunctionArguments(t *testing.T) { Terst(t) test := runTest() + // Should not be able to delete arguments test(` function abc(def, arguments){ @@ -91,7 +96,7 @@ func TestFunctionArguments(t *testing.T) { return def; } abc(1); - `, "1") + `, 1) // Again, should not be able to delete arguments test(` @@ -100,7 +105,7 @@ func TestFunctionArguments(t *testing.T) { return def; } abc(1); - `, "1") + `, 1) // Test typeof of a function argument test(` @@ -119,7 +124,7 @@ func TestFunctionArguments(t *testing.T) { return true; } abc(-1, 4.2, 314); - `, "true") + `, true) } func TestFunctionDeclarationInFunction(t *testing.T) { @@ -129,6 +134,7 @@ func TestFunctionDeclarationInFunction(t *testing.T) { // That is, a function declared within a function will shadow/overwrite // declared parameters test := runTest() + test(` function abc(def){ return def; @@ -252,6 +258,7 @@ func TestFunction_toString(t *testing.T) { Terst(t) test := runTest() + test(`raise: Function.prototype.toString.call(undefined); `, "TypeError") diff --git a/global_test.go b/global_test.go index 203ecf4..7fcfab8 100644 --- a/global_test.go +++ b/global_test.go @@ -3,45 +3,64 @@ package otto import ( . "./terst" "fmt" - //"net/url" + "math" "strings" "testing" - //"unicode/utf16" ) func TestGlobal(t *testing.T) { Terst(t) - Otto, test := runTestWithOtto() - runtime := Otto.runtime + vm, test := runTestWithOtto() + runtime := vm.runtime { - //trueValue, falseValue := TrueValue(), FalseValue() + call := func(object interface{}, src string, argumentList ...interface{}) Value { + var tgt *Object + switch object := object.(type) { + case Value: + tgt = object.Object() + case *Object: + tgt = object + case *_object: + tgt = toValue_object(object).Object() + default: + panic("Here be dragons.") + } + value, err := tgt.Call(src, argumentList...) + Is(err, nil) + return value + } + + value := runtime.localGet("Object")._object().Call(UndefinedValue(), []Value{toValue(runtime.newObject())}) + Is(value.IsObject(), true) + Is(value, "[object Object]") + Is(value._object().prototype == runtime.Global.ObjectPrototype, true) + Is(value._object().prototype == runtime.Global.Object.get("prototype")._object(), true) + Is(value._object().get("toString"), "function toString() { [native code] }") + is(call(value.Object(), "hasOwnProperty", "hasOwnProperty"), false) + + is(call(value._object().get("toString")._object().prototype, "toString"), "function () { [native code] }") // TODO Is this right? + Is(value._object().get("toString")._object().get("toString"), "function toString() { [native code] }") + Is(value._object().get("toString")._object().get("toString")._object(), "function toString() { [native code] }") + + is(call(value._object(), "propertyIsEnumerable", "isPrototypeOf"), false) + value._object().put("xyzzy", toValue_string("Nothing happens."), false) + is(call(value, "propertyIsEnumerable", "isPrototypeOf"), false) + is(call(value, "propertyIsEnumerable", "xyzzy"), true) + Is(value._object().get("xyzzy"), "Nothing happens.") + + is(call(runtime.localGet("Object"), "isPrototypeOf", value), false) + is(call(runtime.localGet("Object")._object().get("prototype"), "isPrototypeOf", value), true) + is(call(runtime.localGet("Function"), "isPrototypeOf", value), false) - result := runtime.localGet("Object")._object().Call(UndefinedValue(), []Value{toValue(runtime.newObject())}) - Is(result.IsObject(), true) - Is(result, "[object Object]") - Is(result._object().prototype == runtime.Global.ObjectPrototype, true) - Is(result._object().prototype == runtime.Global.Object.get("prototype")._object(), true) Is(runtime.newObject().prototype == runtime.Global.Object.get("prototype")._object(), true) - Is(result._object().get("toString"), "function toString() { [native code] }") - //Is(result.Object().CallMethod("hasOwnProperty", "hasOwnProperty"), falseValue) - //Is(result.Object().get("toString").Object().prototype.CallMethod("toString"), "[function]") - //Is(result.Object().get("toString").Object().get("toString").Object(), "[function]") - //Is(result.Object().get("toString").Object().get("toString"), "[function]") - //Is(runtime.localGet("Object").Object().CallMethod("isPrototypeOf", result), falseValue) - //Is(runtime.localGet("Object").Object().get("prototype").Object().CallMethod("isPrototypeOf", result), trueValue) - //Is(runtime.localGet("Function").Object().CallMethod("isPrototypeOf", result), falseValue) - //Is(result.Object().CallMethod("propertyIsEnumerable", "isPrototypeOf"), falseValue) - //result.Object().WriteValue("xyzzy", toValue("Nothing happens."), false) - //Is(result.Object().CallMethod("propertyIsEnumerable", "xyzzy"), trueValue) - //Is(result.Object().get("xyzzy"), "Nothing happens.") - abc := runtime.newBoolean(TrueValue()) - Is(abc, "true") + abc := runtime.newBoolean(toValue_bool(true)) + Is(toValue_object(abc), "true") // TODO Call primitive? def := runtime.localGet("Boolean")._object().Construct(UndefinedValue(), []Value{}) - Is(def, "false") + Is(def, "false") // TODO Call primitive? } test(`new Number().constructor == Number`, true) @@ -105,10 +124,9 @@ func TestGlobalLength(t *testing.T) { test := runTest() - test(`Object.length`, "1") - test(`Function.length`, "1") - test(`RegExp.length`, "2") - test(`Math.length`, "undefined") + test(` + [ Object.length, Function.length, RegExp.length, Math.length ]; + `, "1,1,2,") } func TestGlobalError(t *testing.T) { @@ -116,13 +134,13 @@ func TestGlobalError(t *testing.T) { test := runTest() - test(`TypeError.length`, "1") - test(`TypeError()`, "TypeError") - test(`TypeError("Nothing happens.")`, "TypeError: Nothing happens.") + test(` + [ TypeError.length, TypeError(), TypeError("Nothing happens.") ]; + `, "1,TypeError,TypeError: Nothing happens.") - test(`URIError.length`, "1") - test(`URIError()`, "URIError") - test(`URIError("Nothing happens.")`, "URIError: Nothing happens.") + test(` + [ URIError.length, URIError(), URIError("Nothing happens.") ]; + `, "1,URIError,URIError: Nothing happens.") } func TestGlobalReadOnly(t *testing.T) { @@ -130,20 +148,30 @@ func TestGlobalReadOnly(t *testing.T) { test := runTest() - test(`Number.POSITIVE_INFINITY`, "Infinity") - test(`Number.POSITIVE_INFINITY = 1`, "1") - test(`Number.POSITIVE_INFINITY`, "Infinity") + test(`Number.POSITIVE_INFINITY`, math.Inf(1)) + + test(` + Number.POSITIVE_INFINITY = 1; + `, 1) + + test(`Number.POSITIVE_INFINITY`, math.Inf(1)) + + test(` + Number.POSITIVE_INFINITY = 1; + Number.POSITIVE_INFINITY; + `, math.Inf(1)) } func Test_isNaN(t *testing.T) { Terst(t) test := runTest() - test(`isNaN(0)`, "false") + + test(`isNaN(0)`, false) test(`isNaN("Xyzzy")`, true) test(`isNaN()`, true) test(`isNaN(NaN)`, true) - test(`isNaN(Infinity)`, "false") + test(`isNaN(Infinity)`, false) test(`isNaN.length === 1`, true) test(`isNaN.prototype === undefined`, true) @@ -153,11 +181,12 @@ func Test_isFinite(t *testing.T) { Terst(t) test := runTest() + test(`isFinite(0)`, true) - test(`isFinite("Xyzzy")`, "false") - test(`isFinite()`, "false") - test(`isFinite(NaN)`, "false") - test(`isFinite(Infinity)`, "false") + test(`isFinite("Xyzzy")`, false) + test(`isFinite()`, false) + test(`isFinite(NaN)`, false) + test(`isFinite(Infinity)`, false) test(`isFinite(new Number(451));`, true) test(`isFinite.length === 1`, true) @@ -168,6 +197,7 @@ func Test_parseInt(t *testing.T) { Terst(t) test := runTest() + test(`parseInt("0")`, 0) test(`parseInt("11")`, 11) test(`parseInt(" 11")`, 11) @@ -191,6 +221,7 @@ func Test_parseFloat(t *testing.T) { Terst(t) test := runTest() + test(`parseFloat("0")`, 0) test(`parseFloat("11")`, 11) test(`parseFloat(" 11")`, 11) @@ -219,6 +250,7 @@ func Test_encodeURI(t *testing.T) { Terst(t) test := runTest() + test(`encodeURI("http://example.com/ Nothing happens.")`, "http://example.com/%20Nothing%20happens.") test(`encodeURI("http://example.com/ _^#")`, "http://example.com/%20_%5E#") test(`encodeURI(String.fromCharCode("0xE000"))`, "%EE%80%80") @@ -233,6 +265,7 @@ func Test_encodeURIComponent(t *testing.T) { Terst(t) test := runTest() + test(`encodeURIComponent("http://example.com/ Nothing happens.")`, "http%3A%2F%2Fexample.com%2F%20Nothing%20happens.") test(`encodeURIComponent("http://example.com/ _^#")`, "http%3A%2F%2Fexample.com%2F%20_%5E%23") } @@ -241,6 +274,7 @@ func Test_decodeURI(t *testing.T) { Terst(t) test := runTest() + test(`decodeURI(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") test(`decodeURI(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") test(`raise: decodeURI("http://example.com/ _^#%")`, "URIError: URI malformed") @@ -257,6 +291,7 @@ func Test_decodeURIComponent(t *testing.T) { Terst(t) test := runTest() + test(`decodeURIComponent(encodeURI("http://example.com/ Nothing happens."))`, "http://example.com/ Nothing happens.") test(`decodeURIComponent(encodeURI("http://example.com/ _^#"))`, "http://example.com/ _^#") @@ -274,6 +309,7 @@ func TestGlobal_skipEnumeration(t *testing.T) { Terst(t) test := runTest() + test(` var found = []; for (var test in this) { @@ -285,8 +321,8 @@ func TestGlobal_skipEnumeration(t *testing.T) { found.push(test) } } - found; - `, "") + found.length; + `, 0) test(` var found = []; @@ -311,6 +347,6 @@ func TestGlobal_skipEnumeration(t *testing.T) { found.push(test) } } - found; - `, "") + found.length; + `, 0) } diff --git a/json_test.go b/json_test.go index 3ad4141..eab3ecc 100644 --- a/json_test.go +++ b/json_test.go @@ -3,7 +3,6 @@ package otto import ( . "./terst" "testing" - "time" ) func BenchmarkJSON_parse(b *testing.B) { @@ -23,11 +22,11 @@ func TestJSON_parse(t *testing.T) { test(` JSON.parse("1"); - `, "1") + `, 1) test(` JSON.parse("null"); - `, "null") + `, "null") // TODO Can we make this nil? test(` var abc = JSON.parse('"a\uFFFFbc"'); @@ -40,7 +39,7 @@ func TestJSON_parse(t *testing.T) { test(` JSON.parse('{ "abc": 1, "def":2 }').abc; - `, "1") + `, 1) test(` JSON.parse('{ "abc": { "x": 100, "y": 110 }, "def": [ 10, 20 ,30 ], "ghi": "zazazaza" }').def; @@ -74,9 +73,9 @@ func TestJSON_parse(t *testing.T) { func TestJSON_stringify(t *testing.T) { Terst(t) - test := runTest() + defer mockUTC()() - defer mockTimeLocal(time.UTC)() + test := runTest() test(` JSON.stringify(function(){}); diff --git a/math_test.go b/math_test.go index 9b22807..50dbb13 100644 --- a/math_test.go +++ b/math_test.go @@ -9,6 +9,7 @@ func TestMath_toString(t *testing.T) { Terst(t) test := runTest() + test(`Math.toString()`, "[object Math]") } @@ -16,6 +17,7 @@ func TestMath_abs(t *testing.T) { Terst(t) test := runTest() + test(`Math.abs(NaN)`, "NaN") test(`Math.abs(2)`, "2") test(`Math.abs(-2)`, "2") diff --git a/number_test.go b/number_test.go index b2a4682..e81764b 100644 --- a/number_test.go +++ b/number_test.go @@ -7,7 +7,9 @@ import ( func TestNumber(t *testing.T) { Terst(t) + test := runTest() + test(` var abc = Object.getOwnPropertyDescriptor(Number, "prototype"); [ [ typeof Number.prototype ], diff --git a/panic_test.go b/panic_test.go index b1e749c..04dffd5 100644 --- a/panic_test.go +++ b/panic_test.go @@ -12,17 +12,21 @@ func Test_panic(t *testing.T) { // Test that property.value is set to something if writable is set // to something - // TODO Not panicking anymore? test(` var abc = []; Object.defineProperty(abc, "0", { writable: false }); Object.defineProperty(abc, "0", { writable: false }); "0" in abc; - `, "true") - // `, "false") // TODO Should be true, but we're really testing for a panic + `, true) + + test(`raise: + var abc = []; + Object.defineProperty(abc, "0", { writable: false }); + Object.defineProperty(abc, "0", { value: false, writable: false }); + `, "TypeError") // Test that a regular expression can contain \c0410 (CYRILLIC CAPITAL LETTER A) - // without panic + // without panicking test(` var abc = 0x0410; var def = String.fromCharCode(abc); @@ -33,5 +37,5 @@ func Test_panic(t *testing.T) { test(` new RegExp("\\u0000"); new RegExp("\\undefined").test("undefined"); - `, "true") + `, true) }