luci-base: luci.js: further nested Class.super() call fixes

Use stacks keyed by class id + symbol internally to not clobber the
prototype scope pointer when repeatedly calling super() in invoked
methods.

Ref: https://github.com/openwrt/luci/issues/3316#issuecomment-558531111
Fixes: 374c23cda ("luci-base: luci.js: properly handle nested Class.super() calls")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2019-11-26 11:35:23 +01:00
parent 374c23cdab
commit 4a08fdd2d3

View file

@ -269,33 +269,39 @@
if (key == null)
return null;
var slotIdx = this.__id__ + '.' + key;
var slotIdx = this.__id__ + '.' + key,
symStack = superContext[slotIdx],
protoCtx = null;
for (superContext[slotIdx] = Object.getPrototypeOf(superContext[slotIdx] ||
Object.getPrototypeOf(this));
superContext[slotIdx] && !superContext[slotIdx].hasOwnProperty(key);
superContext[slotIdx] = Object.getPrototypeOf(superContext[slotIdx])) {}
for (protoCtx = Object.getPrototypeOf(symStack ? symStack[0] : Object.getPrototypeOf(this));
protoCtx != null && !protoCtx.hasOwnProperty(key);
protoCtx = Object.getPrototypeOf(protoCtx)) {}
if (!superContext[slotIdx]) {
delete superContext[slotIdx];
if (protoCtx == null)
return null;
}
var res = superContext[slotIdx][key];
var res = protoCtx[key];
if (arguments.length > 1) {
if (typeof(res) != 'function') {
delete superContext[slotIdx];
if (typeof(res) != 'function')
throw new ReferenceError(key + ' is not a function in base class');
}
if (typeof(callArgs) != 'object')
callArgs = this.varargs(arguments, 1);
if (symStack)
symStack.unshift(protoCtx);
else
superContext[slotIdx] = [ protoCtx ];
res = res.apply(this, callArgs);
if (symStack && symStack.length > 1)
symStack.shift(protoCtx);
else
delete superContext[slotIdx];
}
delete superContext[slotIdx];
return res;
},