diff options
author | Jo-Philipp Wich <jo@mein.io> | 2019-11-26 09:37:27 +0100 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2019-11-26 09:37:27 +0100 |
commit | 374c23cdab53c5681acafb561977d927c361408a (patch) | |
tree | c1c45db0eff9572df48c49aa28c8b4929b7399b4 /modules/luci-base/htdocs | |
parent | 666ad2df14ac61fafcc9fa630787f7049cc86e8e (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.js | 29 |
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; }, |