summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/htdocs
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2019-11-26 09:37:27 +0100
committerJo-Philipp Wich <jo@mein.io>2019-11-26 09:37:27 +0100
commit374c23cdab53c5681acafb561977d927c361408a (patch)
treec1c45db0eff9572df48c49aa28c8b4929b7399b4 /modules/luci-base/htdocs
parent666ad2df14ac61fafcc9fa630787f7049cc86e8e (diff)
luci-base: luci.js: properly handle nested Class.super() calls
Introduce a unique __id__ attribute per class and use that, together with the symbol name being looked up to, to form a unique key which is used to store the prototype scope pointer. This fixes cases where a call to super() invokes a procedure which is calling super() as well on a different class or symbol. Fixes: #3316 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'modules/luci-base/htdocs')
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/luci.js29
1 files changed, 19 insertions, 10 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/luci.js b/modules/luci-base/htdocs/luci-static/resources/luci.js
index 7c1831376f..738a5b4cb4 100644
--- a/modules/luci-base/htdocs/luci-static/resources/luci.js
+++ b/modules/luci-base/htdocs/luci-static/resources/luci.js
@@ -67,7 +67,7 @@
* It provides simple means to create subclasses of given classes and
* implements prototypal inheritance.
*/
- var superContext = null, Class = Object.assign(function() {}, {
+ var superContext = {}, classIndex = 0, Class = Object.assign(function() {}, {
/**
* Extends this base class with the properties described in
* `properties` and returns a new subclassed Class instance
@@ -86,8 +86,9 @@
*/
extend: function(properties) {
var props = {
+ __id__: { value: classIndex },
__base__: { value: this.prototype },
- __name__: { value: properties.__name__ || 'anonymous' }
+ __name__: { value: properties.__name__ || 'anonymous' + classIndex++ }
};
var ClassConstructor = function() {
@@ -265,19 +266,28 @@
* superclass method returned `null`.
*/
super: function(key, callArgs) {
- for (superContext = Object.getPrototypeOf(superContext ||
+ if (key == null)
+ return null;
+
+ var slotIdx = this.__id__ + '.' + key;
+
+ for (superContext[slotIdx] = Object.getPrototypeOf(superContext[slotIdx] ||
Object.getPrototypeOf(this));
- superContext && !superContext.hasOwnProperty(key);
- superContext = Object.getPrototypeOf(superContext)) { }
+ superContext[slotIdx] && !superContext[slotIdx].hasOwnProperty(key);
+ superContext[slotIdx] = Object.getPrototypeOf(superContext[slotIdx])) {}
- if (!superContext)
+ if (!superContext[slotIdx]) {
+ delete superContext[slotIdx];
return null;
+ }
- var res = superContext[key];
+ var res = superContext[slotIdx][key];
if (arguments.length > 1) {
- if (typeof(res) != 'function')
+ if (typeof(res) != 'function') {
+ delete superContext[slotIdx];
throw new ReferenceError(key + ' is not a function in base class');
+ }
if (typeof(callArgs) != 'object')
callArgs = this.varargs(arguments, 1);
@@ -285,8 +295,7 @@
res = res.apply(this, callArgs);
}
- superContext = null;
-
+ delete superContext[slotIdx];
return res;
},