diff options
author | Jo-Philipp Wich <jo@mein.io> | 2019-11-26 11:35:23 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2019-11-26 11:39:14 +0100 |
commit | 4a08fdd2d374083366787c4124e6b4de48bf7b77 (patch) | |
tree | ca30681b8ce6c3c6193c9d4ee573b8f8110b0e96 | |
parent | 374c23cdab53c5681acafb561977d927c361408a (diff) |
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>
-rw-r--r-- | modules/luci-base/htdocs/luci-static/resources/luci.js | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/luci.js b/modules/luci-base/htdocs/luci-static/resources/luci.js index 738a5b4cb..808ab0c5c 100644 --- a/modules/luci-base/htdocs/luci-static/resources/luci.js +++ b/modules/luci-base/htdocs/luci-static/resources/luci.js @@ -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; }, |