diff options
Diffstat (limited to 'Godeps/_workspace/src/github.com/robertkrimen/otto/otto_test.go')
-rw-r--r-- | Godeps/_workspace/src/github.com/robertkrimen/otto/otto_test.go | 1379 |
1 files changed, 1379 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_test.go b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_test.go new file mode 100644 index 000000000..2f1e1c35f --- /dev/null +++ b/Godeps/_workspace/src/github.com/robertkrimen/otto/otto_test.go @@ -0,0 +1,1379 @@ +package otto + +import ( + "bytes" + "io" + "testing" + + "github.com/robertkrimen/otto/parser" +) + +func TestOtto(t *testing.T) { + tt(t, func() { + test, _ := test() + + test("xyzzy = 2", 2) + + test("xyzzy + 2", 4) + + test("xyzzy += 16", 18) + + test("xyzzy", 18) + + test(` + (function(){ + return 1 + })() + `, 1) + + test(` + (function(){ + return 1 + }).call(this) + `, 1) + + test(` + (function(){ + var result + (function(){ + result = -1 + })() + return result + })() + `, -1) + + test(` + var abc = 1 + abc || (abc = -1) + abc + `, 1) + + test(` + var abc = (function(){ 1 === 1 })(); + abc; + `, "undefined") + }) +} + +func TestFunction__(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + function abc() { + return 1; + }; + abc(); + `, 1) + }) +} + +func TestIf(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + abc = undefined; + def = undefined; + if (true) abc = 1 + else abc = 2; + if (false) { + def = 3; + } + else def = 4; + + [ abc, def ]; + `, "1,4") + + test(` + if (1) { + abc = 1; + } + else { + abc = 0; + } + abc; + `, 1) + + test(` + if (0) { + abc = 1; + } + else { + abc = 0; + } + abc; + `, 0) + + test(` + abc = 0; + if (0) { + abc = 1; + } + abc; + `, 0) + + test(` + abc = 0; + if (abc) { + abc = 1; + } + abc; + `, 0) + }) +} + +func TestSequence(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + 1, 2, 3; + `, 3) + }) +} + +func TestCall(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + Math.pow(3, 2); + `, 9) + }) +} + +func TestMember(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + abc = [ 0, 1, 2 ]; + def = { + "abc": 0, + "def": 1, + "ghi": 2, + }; + [ abc[2], def.abc, abc[1], def.def ]; + `, "2,0,1,1") + }) +} + +func Test_this(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + typeof this; + `, "object") + }) +} + +func TestWhile(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + limit = 4 + abc = 0 + while (limit) { + abc = abc + 1 + limit = limit - 1 + } + abc; + `, 4) + }) +} + +func TestSwitch_break(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var abc = true; + var ghi = "Xyzzy"; + while (abc) { + switch ('def') { + case 'def': + break; + } + ghi = "Nothing happens."; + abc = false; + } + ghi; + `, "Nothing happens.") + + test(` + var abc = true; + var ghi = "Xyzzy"; + WHILE: + while (abc) { + switch ('def') { + case 'def': + break WHILE; + } + ghi = "Nothing happens." + abc = false + } + ghi; + `, "Xyzzy") + + test(` + var ghi = "Xyzzy"; + FOR: + for (;;) { + switch ('def') { + case 'def': + break FOR; + ghi = ""; + } + ghi = "Nothing happens."; + } + ghi; + `, "Xyzzy") + + test(` + var ghi = "Xyzzy"; + FOR: + for (var jkl in {}) { + switch ('def') { + case 'def': + break FOR; + ghi = "Something happens."; + } + ghi = "Nothing happens."; + } + ghi; + `, "Xyzzy") + + test(` + var ghi = "Xyzzy"; + function jkl() { + switch ('def') { + case 'def': + break; + ghi = ""; + } + ghi = "Nothing happens."; + } + while (abc) { + jkl(); + abc = false; + ghi = "Something happens."; + } + ghi; + `, "Something happens.") + }) +} + +func TestTryFinally(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var abc; + try { + abc = 1; + } + finally { + abc = 2; + } + abc; + `, 2) + + test(` + var abc = false, def = 0; + do { + def += 1; + if (def > 100) { + break; + } + try { + continue; + } + finally { + abc = true; + } + } + while(!abc && def < 10) + def; + `, 1) + + test(` + var abc = false, def = 0, ghi = 0; + do { + def += 1; + if (def > 100) { + break; + } + try { + throw 0; + } + catch (jkl) { + continue; + } + finally { + abc = true; + ghi = 11; + } + ghi -= 1; + } + while(!abc && def < 10) + ghi; + `, 11) + + test(` + var abc = 0, def = 0; + do { + try { + abc += 1; + throw "ghi"; + } + finally { + def = 1; + continue; + } + def -= 1; + } + while (abc < 2) + [ abc, def ]; + `, "2,1") + }) +} + +func TestTryCatch(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var abc = 1; + try { + throw 4; + abc = -1; + } + catch (xyzzy) { + abc += xyzzy + 1; + } + abc; + `, 6) + + test(` + abc = 1; + var def; + try { + try { + throw 4; + abc = -1; + } + catch (xyzzy) { + abc += xyzzy + 1; + throw 64; + } + } + catch (xyzzy) { + def = xyzzy; + abc = -2; + } + [ def, abc ]; + `, "64,-2") + }) +} + +func TestWith(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var def; + with({ abc: 9 }) { + def = abc; + } + def; + `, 9) + + test(` + var def; + with({ abc: function(){ + return 11; + } }) { + def = abc(); + } + def; + `, 11) + }) +} + +func TestSwitch(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var abc = 0; + switch (0) { + default: + abc += 1; + case 1: + abc += 2; + case 2: + abc += 4; + case 3: + abc += 8; + } + abc; + `, 15) + + test(` + abc = 0; + switch (3) { + default: + abc += 1; + case 1: + abc += 2; + case 2: + abc += 4; + case 3: + abc += 8; + } + abc; + `, 8) + + test(` + abc = 0; + switch (60) { + case 1: + abc += 2; + case 2: + abc += 4; + case 3: + abc += 8; + } + abc; + `, 0) + }) +} + +func TestForIn(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var abc; + for (property in { a: 1 }) { + abc = property; + } + abc; + `, "a") + + test(` + var ghi; + for (property in new String("xyzzy")) { + ghi = property; + } + ghi; + `, "4") + }) +} + +func TestFor(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var abc = 7; + for (i = 0; i < 3; i += 1) { + abc += 1; + } + abc; + `, 10) + + test(` + abc = 7; + for (i = 0; i < 3; i += 1) { + abc += 1; + if (i == 1) { + break; + } + } + abc; + `, 9) + + test(` + abc = 7; + for (i = 0; i < 3; i += 1) { + if (i == 2) { + continue; + } + abc += 1; + } + abc; + `, 9) + + test(` + abc = 0; + for (;;) { + abc += 1; + if (abc == 3) + break; + } + abc; + `, 3) + + test(` + for (abc = 0; ;) { + abc += 1; + if (abc == 3) + break; + } + abc; + `, 3) + + test(` + for (abc = 0; ; abc += 1) { + abc += 1; + if (abc == 3) + break; + } + abc; + `, 3) + }) +} + +func TestLabelled(t *testing.T) { + tt(t, func() { + test, _ := test() + + // TODO Add emergency break + + test(` + xyzzy: for (var abc = 0; abc <= 0; abc++) { + for (var def = 0; def <= 1; def++) { + if (def === 0) { + continue xyzzy; + } else { + } + } + } + `) + + test(` + abc = 0 + def: + while (true) { + while (true) { + abc = abc + 1 + if (abc > 11) { + break def; + } + } + } + abc; + `, 12) + + test(` + abc = 0 + def: + do { + do { + abc = abc + 1 + if (abc > 11) { + break def; + } + } while (true) + } while (true) + abc; + `, 12) + }) +} + +func TestConditional(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + [ true ? false : true, true ? 1 : 0, false ? 3.14159 : "abc" ]; + `, "false,1,abc") + }) +} + +func TestArrayLiteral(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + [ 1, , 3.14159 ]; + `, "1,,3.14159") + }) +} + +func TestAssignment(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var abc = 1; + abc; + `, 1) + + test(` + abc += 2; + abc; + `, 3) + }) +} + +func TestBinaryOperation(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(`0 == 1`, false) + test(`1 == "1"`, true) + test(`0 === 1`, false) + test(`1 === "1"`, false) + test(`"1" === "1"`, true) + }) +} + +func Test_typeof(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(`typeof abc`, "undefined") + test(`typeof abc === 'undefined'`, true) + test(`typeof {}`, "object") + test(`typeof null`, "object") + }) +} + +func Test_PrimitiveValueObjectValue(t *testing.T) { + tt(t, func() { + test, _ := test() + + Number11 := test(`new Number(11)`) + is(Number11.float64(), 11) + }) +} + +func Test_eval(t *testing.T) { + tt(t, func() { + test, _ := test() + + // FIXME terst, Is this correct? + test(` + var abc = 1; + `, "undefined") + + test(` + eval("abc += 1"); + `, 2) + + test(` + (function(){ + var abc = 11; + eval("abc += 1"); + return abc; + })(); + `, 12) + test(`abc`, 2) + + test(` + (function(){ + try { + eval("var prop = \\u2029;"); + return false; + } catch (abc) { + return [ abc instanceof SyntaxError, abc.toString() ]; + } + })(); + `, "true,SyntaxError: Unexpected token ILLEGAL") + + test(` + function abc(){ + this.THIS = eval("this"); + } + var def = new abc(); + def === def.THIS; + `, true) + }) +} + +func Test_evalDirectIndirect(t *testing.T) { + tt(t, func() { + test, _ := test() + + // (function () {return this;}()).abc = "global"; + test(` + var abc = "global"; + (function(){ + try { + var _eval = eval; + var abc = "function"; + return [ + _eval("\'global\' === abc"), // eval (Indirect) + eval("\'function\' === abc"), // eval (Direct) + ]; + } finally { + delete this.abc; + } + })(); + `, "true,true") + }) +} + +func TestError_URIError(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(`new URIError() instanceof URIError`, true) + + test(` + var abc + try { + decodeURI("http://example.com/ _^#%") + } + catch (def) { + abc = def instanceof URIError + } + abc + `, true) + }) +} + +func TestTo(t *testing.T) { + tt(t, func() { + test, _ := test() + + { + value, _ := test(`"11"`).ToFloat() + is(value, float64(11)) + } + + { + value, _ := test(`"11"`).ToInteger() + is(value, int64(11)) + + value, _ = test(`1.1`).ToInteger() + is(value, int64(1)) + } + }) +} + +func TestShouldError(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(`raise: + xyzzy + throw new TypeError("Nothing happens.") + `, "ReferenceError: 'xyzzy' is not defined") + }) +} + +func TestAPI(t *testing.T) { + tt(t, func() { + test, vm := test() + + test(` + String.prototype.xyzzy = function(){ + return this.length + 11 + (arguments[0] || 0) + } + abc = new String("xyzzy") + def = "Nothing happens." + abc.xyzzy() + `, 16) + abc, _ := vm.Get("abc") + def, _ := vm.Get("def") + object := abc.Object() + result, _ := object.Call("xyzzy") + is(result, 16) + result, _ = object.Call("xyzzy", 1) + is(result, 17) + value, _ := object.Get("xyzzy") + result, _ = value.Call(def) + is(result, 27) + result, _ = value.Call(def, 3) + is(result, 30) + object = value.Object() // Object xyzzy + result, _ = object.Value().Call(def, 3) + is(result, 30) + + test(` + abc = { + 'abc': 1, + 'def': false, + 3.14159: NaN, + }; + abc['abc']; + `, 1) + abc, err := vm.Get("abc") + is(err, nil) + object = abc.Object() // Object abc + value, err = object.Get("abc") + is(err, nil) + is(value, 1) + is(object.Keys(), []string{"abc", "def", "3.14159"}) + + test(` + abc = [ 0, 1, 2, 3.14159, "abc", , ]; + abc.def = true; + `) + abc, err = vm.Get("abc") + is(err, nil) + object = abc.Object() // Object abc + is(object.Keys(), []string{"0", "1", "2", "3", "4", "def"}) + }) +} + +func TestUnicode(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(`var abc = eval("\"a\uFFFFa\"");`, "undefined") + + test(`abc.length`, 3) + + test(`abc != "aa"`, true) + + test("abc[1] === \"\uFFFF\"", true) + }) +} + +func TestDotMember(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + abc = { + ghi: 11, + } + abc.def = "Xyzzy" + abc.null = "Nothing happens." + `) + test(`abc.def`, "Xyzzy") + test(`abc.null`, "Nothing happens.") + test(`abc.ghi`, 11) + + test(` + abc = { + null: 11, + } + `) + test(`abc.def`, "undefined") + test(`abc.null`, 11) + test(`abc.ghi`, "undefined") + }) +} + +func Test_stringToFloat(t *testing.T) { + tt(t, func() { + + is(parseNumber("10e10000"), _Infinity) + is(parseNumber("10e10_."), _NaN) + }) +} + +func Test_delete(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + delete 42; + `, true) + + test(` + var abc = delete $_undefined_$; + abc = abc && delete ($_undefined_$); + abc; + `, true) + + // delete should not trigger get() + test(` + var abc = { + get def() { + throw "Test_delete: delete should not trigger get()" + } + }; + delete abc.def + `, true) + }) +} + +func TestObject_defineOwnProperty(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var object = {}; + + var descriptor = new Boolean(false); + descriptor.configurable = true; + + Object.defineProperties(object, { + property: descriptor + }); + + var abc = object.hasOwnProperty("property"); + delete object.property; + var def = object.hasOwnProperty("property"); + + [ abc, def ]; + `, "true,false") + + test(` + var object = [0, 1, 2]; + Object.defineProperty(object, "0", { + value: 42, + writable: false, + enumerable: false, + configurable: false + }); + var abc = Object.getOwnPropertyDescriptor(object, "0"); + [ abc.value, abc.writable, abc.enumerable, abc.configurable ]; + `, "42,false,false,false") + + test(` + var abc = { "xyzzy": 42 }; + var def = Object.defineProperties(abc, ""); + abc === def; + `, true) + }) +} + +func Test_assignmentEvaluationOrder(t *testing.T) { + tt(t, func() { + test, _ := test() + + test(` + var abc = 0; + ((abc = 1) & abc); + `, 1) + + test(` + var abc = 0; + (abc & (abc = 1)); + `, 0) + }) +} + +func TestOttoCall(t *testing.T) { + tt(t, func() { + vm := New() + + _, err := vm.Run(` + var abc = { + ghi: 1, + def: function(def){ + var ghi = 0; + if (this.ghi) { + ghi = this.ghi; + } + return "def: " + (def + 3.14159 + ghi); + } + }; + `) + is(err, nil) + + value, err := vm.Call(`abc.def`, nil, 2) + is(err, nil) + is(value, "def: 6.14159") + + value, err = vm.Call(`abc.def`, "", 2) + is(err, nil) + is(value, "def: 5.14159") + + // Do not attempt to do a ToValue on a this of nil + value, err = vm.Call(`jkl.def`, nil, 1, 2, 3) + is(err, "!=", nil) + is(value, "undefined") + + value, err = vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, "abc") + is(err, nil) + is(value, "1,2,3,,4,5,6,7,abc") + }) +} + +func TestOttoCall_new(t *testing.T) { + tt(t, func() { + test, vm := test() + + vm.Set("abc", func(call FunctionCall) Value { + value, err := call.Otto.Call(`new Object`, nil, "Nothing happens.") + is(err, nil) + return value + }) + test(` + def = abc(); + [ def, def instanceof String ]; + `, "Nothing happens.,true") + }) +} + +func TestOttoCall_throw(t *testing.T) { + // FIXME? (Been broken for a while) + // Looks like this has been broken for a while... what + // behavior do we want here? + + if true { + return + } + + tt(t, func() { + test, vm := test() + + vm.Set("abc", func(call FunctionCall) Value { + if false { + call.Otto.Call(`throw eval`, nil, "({ def: 3.14159 })") + } + call.Otto.Call(`throw Error`, nil, "abcdef") + return Value{} + }) + // TODO try { abc(); } catch (err) { error = err } + // Possible unrelated error case: + // If error is not declared beforehand, is later referencing it a ReferenceError? + // Should the catch { } declare error in the outer scope? + test(` + var error; + try { + abc(); + } + catch (err) { + error = err; + } + [ error instanceof Error, error.message, error.def ]; + `, "true,abcdef,") + + vm.Set("def", func(call FunctionCall) Value { + call.Otto.Call(`throw new Object`, nil, 3.14159) + return UndefinedValue() + }) + test(` + try { + def(); + } + catch (err) { + error = err; + } + [ error instanceof Error, error.message, error.def, typeof error, error, error instanceof Number ]; + `, "false,,,object,3.14159,true") + }) +} + +func TestOttoCopy(t *testing.T) { + tt(t, func() { + vm0 := New() + vm0.Run(` + var abc = function() { + return "Xyzzy"; + }; + + function def() { + return abc() + (0 + {}); + } + `) + + value, err := vm0.Run(` + def(); + `) + is(err, nil) + is(value, "Xyzzy0[object Object]") + + vm1 := vm0.Copy() + value, err = vm1.Run(` + def(); + `) + is(err, nil) + is(value, "Xyzzy0[object Object]") + + vm1.Run(` + abc = function() { + return 3.14159; + }; + `) + value, err = vm1.Run(` + def(); + `) + is(err, nil) + is(value, "3.141590[object Object]") + + value, err = vm0.Run(` + def(); + `) + is(err, nil) + is(value, "Xyzzy0[object Object]") + + { + vm0 := New() + vm0.Run(` + var global = (function () {return this;}()) + var abc = 0; + var vm = "vm0"; + + var def = (function(){ + var jkl = 0; + var abc = function() { + global.abc += 1; + jkl += 1; + return 1; + }; + + return function() { + return [ vm, global.abc, jkl, abc() ]; + }; + })(); + `) + + value, err := vm0.Run(` + def(); + `) + is(err, nil) + is(value, "vm0,0,0,1") + + vm1 := vm0.Copy() + vm1.Set("vm", "vm1") + value, err = vm1.Run(` + def(); + `) + is(err, nil) + is(value, "vm1,1,1,1") + + value, err = vm0.Run(` + def(); + `) + is(err, nil) + is(value, "vm0,1,1,1") + + value, err = vm1.Run(` + def(); + `) + is(err, nil) + is(value, "vm1,2,2,1") + } + }) +} + +func TestOttoCall_clone(t *testing.T) { + tt(t, func() { + vm := New().clone() + rt := vm.runtime + + { + // FIXME terst, Check how this comparison is done + is(rt.global.Array.prototype, rt.global.FunctionPrototype) + is(rt.global.ArrayPrototype, "!=", nil) + is(rt.global.Array.runtime, rt) + is(rt.global.Array.prototype.runtime, rt) + is(rt.global.Array.get("prototype")._object().runtime, rt) + } + + { + value, err := vm.Run(`[ 1, 2, 3 ].toString()`) + is(err, nil) + is(value, "1,2,3") + } + + { + value, err := vm.Run(`[ 1, 2, 3 ]`) + is(err, nil) + is(value, "1,2,3") + object := value._object() + is(object, "!=", nil) + is(object.prototype, rt.global.ArrayPrototype) + + value, err = vm.Run(`Array.prototype`) + is(err, nil) + object = value._object() + is(object.runtime, rt) + is(object, "!=", nil) + is(object, rt.global.ArrayPrototype) + } + + { + otto1 := New() + _, err := otto1.Run(` + var abc = 1; + var def = 2; + `) + is(err, nil) + + otto2 := otto1.clone() + value, err := otto2.Run(`abc += 1; abc;`) + is(err, nil) + is(value, 2) + + value, err = otto1.Run(`abc += 4; abc;`) + is(err, nil) + is(value, 5) + } + + { + vm1 := New() + _, err := vm1.Run(` + var abc = 1; + var def = function(value) { + abc += value; + return abc; + } + `) + is(err, nil) + + vm2 := vm1.clone() + value, err := vm2.Run(`def(1)`) + is(err, nil) + is(value, 2) + + value, err = vm1.Run(`def(4)`) + is(err, nil) + is(value, 5) + } + + { + vm1 := New() + _, err := vm1.Run(` + var abc = { + ghi: 1, + jkl: function(value) { + this.ghi += value; + return this.ghi; + } + }; + var def = { + abc: abc + }; + `) + is(err, nil) + + otto2 := vm1.clone() + value, err := otto2.Run(`def.abc.jkl(1)`) + is(err, nil) + is(value, 2) + + value, err = vm1.Run(`def.abc.jkl(4)`) + is(err, nil) + is(value, 5) + } + + { + vm1 := New() + _, err := vm1.Run(` + var abc = function() { return "abc"; }; + var def = function() { return "def"; }; + `) + is(err, nil) + + vm2 := vm1.clone() + value, err := vm2.Run(` + [ abc.toString(), def.toString() ]; + `) + is(value, `function() { return "abc"; },function() { return "def"; }`) + + _, err = vm2.Run(` + var def = function() { return "ghi"; }; + `) + is(err, nil) + + value, err = vm1.Run(` + [ abc.toString(), def.toString() ]; + `) + is(value, `function() { return "abc"; },function() { return "def"; }`) + + value, err = vm2.Run(` + [ abc.toString(), def.toString() ]; + `) + is(value, `function() { return "abc"; },function() { return "ghi"; }`) + } + + }) +} + +func TestOttoRun(t *testing.T) { + tt(t, func() { + vm := New() + + program, err := parser.ParseFile(nil, "", "", 0) + is(err, nil) + value, err := vm.Run(program) + is(err, nil) + is(value, UndefinedValue()) + + program, err = parser.ParseFile(nil, "", "2 + 2", 0) + is(err, nil) + value, err = vm.Run(program) + is(err, nil) + is(value, 4) + value, err = vm.Run(program) + is(err, nil) + is(value, 4) + + program, err = parser.ParseFile(nil, "", "var abc; if (!abc) abc = 0; abc += 2; abc;", 0) + value, err = vm.Run(program) + is(err, nil) + is(value, 2) + value, err = vm.Run(program) + is(err, nil) + is(value, 4) + value, err = vm.Run(program) + is(err, nil) + is(value, 6) + + { + src := []byte("var abc; if (!abc) abc = 0; abc += 2; abc;") + value, err = vm.Run(src) + is(err, nil) + is(value, 8) + + value, err = vm.Run(bytes.NewBuffer(src)) + is(err, nil) + is(value, 10) + + value, err = vm.Run(io.Reader(bytes.NewBuffer(src))) + is(err, nil) + is(value, 12) + } + + { + script, err := vm.Compile("", `var abc; if (!abc) abc = 0; abc += 2; abc;`) + is(err, nil) + + value, err = vm.Run(script) + is(err, nil) + is(value, 14) + + value, err = vm.Run(script) + is(err, nil) + is(value, 16) + + is(script.String(), "// \nvar abc; if (!abc) abc = 0; abc += 2; abc;") + } + }) +} + +func Test_objectLength(t *testing.T) { + tt(t, func() { + _, vm := test() + + value := vm.Set("abc", []string{"jkl", "mno"}) + is(objectLength(value._object()), 2) + + value, _ = vm.Run(`[1, 2, 3]`) + is(objectLength(value._object()), 3) + + value, _ = vm.Run(`new String("abcdefghi")`) + is(objectLength(value._object()), 9) + + value, _ = vm.Run(`"abcdefghi"`) + is(objectLength(value._object()), 0) + }) +} + +func BenchmarkNew(b *testing.B) { + for i := 0; i < b.N; i++ { + New() + } +} + +func BenchmarkClone(b *testing.B) { + vm := New() + b.ResetTimer() + for i := 0; i < b.N; i++ { + vm.clone() + } +} |