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.
 
 
 
 
 
 

55 lines
1.6 KiB

/*
* Bug reported by: http://www.reddit.com/user/judofyr
*
* The trigger for the bug is "return reduce(..." tailcall in the flatten
* function. For some reason the 'shallow' variable access doesn't work
* correctly. If the code is changed to "var res = reduce(...); return res;"
* it works in Duktape 0.8.0.
*
*/
/* Incorrect output from Duktape 0.8.0:
function empty() {...}
function empty() {...}
[1,2,3,[[[4]]]]
*/
/*===
undefined
undefined
undefined
undefined
undefined
[1,2,3,4]
===*/
try {
var reduce = function(obj, iterator, memo) {
return obj.reduce(iterator, memo);
};
var flatten = function(array, shallow) {
/* The problem here with a tailcall is that the flatten() invocation will
* be replaced in the callstack without an explicit unwind. The GETVAR
* for 'shallow' will still match to the outer lexical environment but the
* environment will not be closed.
*
* As a result, the 'shallow' lookup will look up an unrelated register and
* return the incorrect 'function' value. The fix is to ensure that the
* current activation is closed on a TAILCALL.
*/
return reduce(array, function(memo, value) {
if (Array.isArray(value)) {
print(shallow); // this should print undef
return memo.concat(shallow ? value : flatten(value));
} else {
memo[memo.length] = value;
}
return memo;
}, []);
}
print(JSON.stringify(flatten([1, [2], [3, [[[4]]]]]))); // [1,2,3,4]
} catch (e) {
print(e)
}