Browse Source

Merge pull request #1135 from svaarala/fix-bound-function-prototype

Fix bound function internal prototype handling to match ES6
pull/1141/head
Sami Vaarala 8 years ago
committed by GitHub
parent
commit
57af66a5bd
  1. 4
      RELEASES.rst
  2. 4
      doc/release-notes-v2-0.rst
  3. 10
      src-input/duk_bi_function.c
  4. 39
      tests/ecmascript/test-dev-bound-func-prototype.js

4
RELEASES.rst

@ -1996,6 +1996,10 @@ Planned
for a target function with name "foo", bound function name is "bound foo"
(GH-1113)
* Change bound function internal prototype handling to match ES6 requirements;
bound function internal prototype is copied from the target function
instead of always being Function.prototype (GH-1135)
* Add a fastint check for duk_put_number_list() values (GH-1086)
* Remove an unintended fastint downgrade check for unary minus executor

4
doc/release-notes-v2-0.rst

@ -1058,6 +1058,10 @@ Other incompatible changes
"enumerate" trap has been obsoleted. Key enumerability is also now checked
when "ownKeys" trap is used in Object.keys() and for-in.
* Bound function internal prototype is copied from the target function to match
ES6 requirements; in ES5 (and Duktape 1.x) bound function internal prototype
is always set to Function.prototype.
Known issues
============

10
src-input/duk_bi_function.c

@ -302,6 +302,7 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_call(duk_context *ctx) {
* merges argument lists etc here.
*/
DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
duk_hthread *thr = (duk_hthread *) ctx;
duk_hobject *h_bound;
duk_hobject *h_target;
duk_idx_t nargs;
@ -349,8 +350,15 @@ DUK_INTERNAL duk_ret_t duk_bi_function_prototype_bind(duk_context *ctx) {
/* [ thisArg arg1 ... argN func boundFunc ] */
/* bound function 'length' property is interesting */
h_target = duk_get_hobject(ctx, -2);
/* internal prototype must be copied from the target */
if (h_target != NULL) {
/* For lightfuncs Function.prototype is used and is already in place. */
DUK_HOBJECT_SET_PROTOTYPE_UPDREF(thr, h_bound, DUK_HOBJECT_GET_PROTOTYPE(thr->heap, h_target));
}
/* bound function 'length' property is interesting */
if (h_target == NULL || /* lightfunc */
DUK_HOBJECT_GET_CLASS_NUMBER(h_target) == DUK_HOBJECT_CLASS_FUNCTION) {
/* For lightfuncs, simply read the virtual property. */

39
tests/ecmascript/test-dev-bound-func-prototype.js

@ -0,0 +1,39 @@
/*
* Bound function internal prototype is copied from the target in ES6.
* In ES5 it is always Function.prototype. Test for ES6 behavior.
*/
/*===
bar
bar
true
quux
bar
false
===*/
function test() {
var F = function foo() {};
var proto = { foo: 'bar' };
Object.setPrototypeOf(F, proto);
// Create a bound function; its prototype is copied from the current
// prototype of the target.
var G = Function.prototype.bind.call(F);
print(F.foo);
print(G.foo);
print(Object.getPrototypeOf(G) === proto);
// Alter target's internal prototype; doesn't affect the bound function.
proto = { foo: 'quux' };
Object.setPrototypeOf(F, proto);
print(F.foo);
print(G.foo);
print(Object.getPrototypeOf(G) === proto);
}
try {
test();
} catch (e) {
print(e.stack || e);
}
Loading…
Cancel
Save