mirror of https://github.com/svaarala/duktape.git
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.
56 lines
1.6 KiB
56 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)
|
|
}
|
|
|
|
|