Prevent consumed properties in object literal constructors from being set on the instance.

We need to make sure arguments.__filtered survives constructor calls.
This commit is contained in:
Jürg Lehni 2017-04-22 13:52:03 +02:00
parent e46c8ec340
commit b26b056522
2 changed files with 22 additions and 6 deletions

View file

@ -141,6 +141,12 @@ var Rectangle = Base.extend(/** @lends Rectangle# */{
}
this._set(x, y, width, height);
read = arguments.__index;
// arguments.__filtered wouldn't survive the function call even if a
// previous arguments list was passed through Function#apply().
// Return it on the object instead, see Base.read()
var filtered = arguments.__filtered;
if (filtered)
this.__filtered = filtered;
}
if (this.__read)
this.__read = read;

View file

@ -208,6 +208,14 @@ Base.inject(/** @lends Base# */{
: list) || obj;
if (readIndex) {
list.__index = begin + obj.__read;
// This is only in use in Rectangle so far: Nested calls to
// Base.readNamed() would loose __filtered if it wasn't returned
// on the object.
var filtered = obj.__filtered;
if (filtered) {
list.__filtered = filtered;
obj.__filtered = undefined;
}
obj.__read = undefined;
}
return obj;
@ -281,18 +289,20 @@ Base.inject(/** @lends Base# */{
if (hasObject) {
// Create a _filtered object that inherits from list[0], and
// override all fields that were already read with undefined.
var filtered = list._filtered;
var filtered = list.__filtered;
if (!filtered) {
filtered = list._filtered = Base.create(list[0]);
filtered = list.__filtered = Base.create(list[0]);
// Point _unfiltered to the original so Base#_set() can
// execute hasOwnProperty on it.
filtered._unfiltered = list[0];
filtered.__unfiltered = list[0];
}
// delete wouldn't work since the masked parent's value would
// shine through.
filtered[name] = undefined;
}
return this.read(hasObject ? [value] : list, start, options, amount);
var l = hasObject ? [value] : list,
res = this.read(l, start, options, amount);
return res;
},
/**
@ -307,7 +317,7 @@ Base.inject(/** @lends Base# */{
list._hasObject = list.length === 1 && Base.isPlainObject(arg);
if (list._hasObject)
// Return the whole arguments object if no name is provided.
return name ? arg[name] : list._filtered || arg;
return name ? arg[name] : list.__filtered || arg;
},
/**
@ -365,7 +375,7 @@ Base.inject(/** @lends Base# */{
// If source is a filtered object, we get the keys from the
// the original object (it's parent / prototype). See _filtered
// inheritance trick in the argument reading code.
Object.keys(source._unfiltered || source).forEach(handleKey);
Object.keys(source.__unfiltered || source).forEach(handleKey);
return dest;
},