You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

332 lines
9.1 KiB

// double a number or concatenate a string with itself
function retTwice(val, key, obj) {
print(typeof this, this, typeof val, val, typeof key, key, typeof obj, obj);
return val + val;
}
function test(this_value, args) {
var t;
try {
t = Array.prototype.map.apply(this_value, args);
print(typeof t, t);
} catch (e) {
print(e.name);
}
}
/*===
basic
object
object [object global] number 1 number 0 object 1
object 2
object [object global] number 1 number 0 object 1,2
object [object global] number 2 number 1 object 1,2
object 2,4
object [object global] number 1 number 0 object 1,2,3,4,5
object [object global] number 2 number 1 object 1,2,3,4,5
object [object global] number 3 number 2 object 1,2,3,4,5
object [object global] number 4 number 3 object 1,2,3,4,5
object [object global] number 5 number 4 object 1,2,3,4,5
object 2,4,6,8,10
object [object global] number 1 number 0 object 1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3
object [object global] number 2 number 50 object 1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3
object [object global] number 3 number 100 object 1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,3
object 2,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,4,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,6
object [object global] string foo number 0 object [object Object]
object [object global] string bar number 5 object [object Object]
object [object global] string quux number 20 object [object Object]
object foofoo,,,,,barbar,,,,,,,,,,,,,,,quuxquux
callback 1
CallbackError
nonstrict object
nonstrict object
nonstrict object
object 101,102,103
nonstrict object
nonstrict object
nonstrict object
object 101,102,103
nonstrict object
nonstrict object
nonstrict object
object 101,102,103
strict undefined undefined
strict undefined undefined
strict undefined undefined
object 101,102,103
strict object null
strict object null
strict object null
object 101,102,103
strict string foo
strict string foo
strict string foo
object 101,102,103
callback 1 0 1,2,3,4,5,6,7,8,9,10
callback 2 1 1,2,3,4,5,6,7,8,9,10
callback 3 2 1,2,3,4,5,6,7,8,9,10
callback 4 3 1,2,3,4,5,6,7,8,9,10
callback 5 4 1,2,3,4,5,6,7,8,9,10
callback 6 5 1,2,3,4,5,6,7,8,9,10
callback 7 6 1,2,3,4,5,6,7,8,9,10
callback 8 7 1,2,3,4,5,6,7,8,9,10
callback 9 8 1,2,3,4,5,6,7,8,9,10
callback 10 9 1,2,3,4,5,6,7,8,9,10
object ,,true,false,123,foo,1,2,[object Object],,
===*/
print('basic');
function basicTest() {
var obj;
// simple cases
test([], [ retTwice ]);
test([1], [ retTwice ]);
test([1,2], [ retTwice ]);
// dense
test([1,2,3,4,5], [ retTwice ]);
// sparse
obj = [1];
obj[100] = 3;
obj[50] = 2;
test(obj, [ retTwice ]);
// sparse with trailing non-existent elements: for this case standard and
// real world behaviors differ, so this is covered by a separate test case:
// test-bi-array-proto-map-nonstd-trailing.js
// non-array; careful to avoid trailing non-existent elements (tested
// separately)
obj = { '0': 'foo', '5': 'bar', '20': 'quux', '100': 'baz', length: 21 };
test(obj, [ retTwice ]);
// error in callback propagates outwards
test([1,2,3], [ function(val, key, obj) {
var e;
print('callback', val);
e = new Error('callback error');
e.name = 'CallbackError';
throw e;
}]);
// this binding, non-strict callbacks gets a coerced binding
test([1,2,3], [ function(val, key, obj) {
print('nonstrict', typeof this);
return val + 100;
}]);
test([1,2,3], [ function(val, key, obj) {
print('nonstrict', typeof this);
return val + 100;
}, null]);
test([1,2,3], [ function(val, key, obj) {
print('nonstrict', typeof this);
return val + 100;
}, 'foo']);
test([1,2,3], [ function(val, key, obj) {
'use strict';
print('strict', typeof this, this);
return val + 100;
}]);
test([1,2,3], [ function(val, key, obj) {
'use strict';
print('strict', typeof this, this);
return val + 100;
}, null]); // Note: typeof null -> 'object'
test([1,2,3], [ function(val, key, obj) {
'use strict';
print('strict', typeof this, this);
return val + 100;
}, 'foo']);
// return value is used as is; note that undefined and null both print
// as empty string when array toString() is called
var testvalues = [ undefined, null, true, false, 123, 'foo', [1,2], { foo: 1, bar: 2 } ];
test([1,2,3,4,5,6,7,8,9,10], [ function (val, key, obj) {
print('callback', val, key, obj);
return testvalues[key];
} ]);
}
try {
basicTest();
} catch (e) {
print(e);
}
/*===
mutation
foo 0 foo,bar,quux
bar 1 foo,bar,quux,baz
quux 2 foo,bar,quux,baz
object mapped-foo,mapped-bar,mapped-quux
foo 0 foo,bar,quux
quux 2 foo,,quux
object mapped-foo,,mapped-quux
foo 0 [object Object]
bar 1 [object Object]
quux 2 [object Object]
object mapped-foo,mapped-bar,mapped-quux
foo 0 [object Object]
quux 2 [object Object]
object mapped-foo,,mapped-quux
===*/
print('mutation');
function mutationTest() {
var obj;
// added element not recognized
obj = [ 'foo', 'bar', 'quux' ];
test(obj, [ function (val, key, obj) {
print(val, key, obj);
obj[3] = 'baz';
return 'mapped-' + val;
}]);
// deleted element not processed
obj = [ 'foo', 'bar', 'quux' ];
test(obj, [ function (val, key, obj) {
print(val, key, obj);
delete obj[1];
return 'mapped-' + val;
}]);
// same for non-array
obj = { '0': 'foo', '1': 'bar', '2': 'quux', '3': 'baz', length: 3 };
test(obj, [ function (val, key, obj) {
print(val, key, obj);
obj[4] = 'quuux';
obj.length = 10;
return 'mapped-' + val;
}]);
obj = { '0': 'foo', '1': 'bar', '2': 'quux', '3': 'baz', length: 3 };
test(obj, [ function (val, key, obj) {
print(val, key, obj);
delete obj[3]; delete obj[1];
obj.length = 0;
return 'mapped-' + val;
}]);
}
try {
mutationTest();
} catch (e) {
print(e);
}
/*===
coercion
TypeError
TypeError
object
object
object
object [object global] string f number 0 object foo
object [object global] string o number 1 object foo
object [object global] string o number 2 object foo
object ff,oo,oo
object [object global] number 1 number 0 object 1,2,3
object [object global] number 2 number 1 object 1,2,3
object [object global] number 3 number 2 object 1,2,3
object 2,4,6
object
object [object global] string foo number 0 object [object Object]
object [object global] string bar number 1 object [object Object]
object [object global] string quux number 2 object [object Object]
object foofoo,barbar,quuxquux
object [object global] string foo number 0 object [object Object]
object [object global] string bar number 1 object [object Object]
object [object global] string quux number 2 object [object Object]
object foofoo,barbar,quuxquux
object [object global] string foo number 0 object [object Object]
object [object global] string bar number 1 object [object Object]
object [object global] string quux number 2 object [object Object]
object [object global] string baz number 3 object [object Object]
object foofoo,barbar,quuxquux,bazbaz
length valueOf
object [object global] string foo number 0 object [object Object]
object [object global] string bar number 1 object [object Object]
object [object global] string quux number 2 object [object Object]
object foofoo,barbar,quuxquux
length valueOf
TypeError
===*/
print('coercion');
function coercionTest() {
var obj;
// this
test(undefined, [ retTwice ]);
test(null, [ retTwice ]);
test(true, [ retTwice ]);
test(false, [ retTwice ]);
test(123, [ retTwice ]);
test('foo', [ retTwice ]);
test([1,2,3], [ retTwice ]);
test({ foo: 1, bar: 2 }, [ retTwice ]);
// length
obj = { '0': 'foo', '1': 'bar', '2': 'quux', '3': 'baz', '4': 'quux', length: '3.9' };
test(obj, [ retTwice ]);
obj = { '0': 'foo', '1': 'bar', '2': 'quux', '3': 'baz', '4': 'quux', length: 256*256*256*256 + 3.9 }; // coerces to 3
test(obj, [ retTwice ]);
obj = { '0': 'foo', '1': 'bar', '2': 'quux', '3': 'baz', '4': 'quux', length: -256*256*256*256 + 3.9 }; // coerces to 4
test(obj, [ retTwice ]);
obj = { '0': 'foo', '1': 'bar', '2': 'quux', 'length': {
toString: function() {
print('length toString');
return 4;
},
valueOf: function() {
print('length valueOf');
return 3;
}
}};
test(obj, [ retTwice ]);
// callable check is done after length coercion
obj = { '0': 'foo', '1': 'bar', '2': 'quux', 'length': {
toString: function() {
print('length toString');
return 4;
},
valueOf: function() {
print('length valueOf');
return 3;
}
}};
test(obj, [ null ]);
}
try {
coercionTest();
} catch (e) {
print(e);
}