From 17a476edaaf81f72e6b1c9d5903ddeb48dcd1e74 Mon Sep 17 00:00:00 2001 From: Nicolas Petton Date: Wed, 26 Apr 2017 15:05:29 +0200 Subject: [PATCH] Optimize supercall installation Do not lookup on which methods we need to install supercalls each time an instance is created. Instead, we cache in a non-enumerable variable `methodsWithSuperCall` on each class all method names that need supercall installation. --- dist/klassified.js | 48 ++++++++++++++++++++++++++++++++---------- dist/klassified.min.js | 2 +- src/object.js | 48 ++++++++++++++++++++++++++++++++---------- 3 files changed, 75 insertions(+), 23 deletions(-) diff --git a/dist/klassified.js b/dist/klassified.js index 35c41da..df55f3d 100644 --- a/dist/klassified.js +++ b/dist/klassified.js @@ -628,9 +628,10 @@ define('object',[], function() { }); builder(instance, my); + if (superCallRegex.test(builder)) { - installSuper(instance, superInstance); - installSuper(my, superMy); + installSuper(my, superMy, klass, "my"); + installSuper(instance, superInstance, klass, "that"); } if (!notFinal) { @@ -704,15 +705,12 @@ define('object',[], function() { * `super` from within each public function of `obj` to the function in * `proto`. */ - function installSuper(obj, proto) { - Object.keys(obj).forEach(function(name) { - if (typeof proto[name] === "function" && - typeof obj[name] === "function" && - superCallRegex.test(obj[name]) && - !obj[name].superInstalled) { - var superFn = proto[name]; - obj[name] = (function(name, fn) { + function installSuper(obj, proto, klass, receiverName) { + methodsWithSuperCall(obj, proto, klass, receiverName).forEach(function(name) { + if (!obj[name].superInstalled) { + obj[name] = (function(obj, fn, superFn) { return function() { + var tmp = obj.super; obj.super = superFn; var returnValue = fn.apply(obj, arguments); @@ -726,12 +724,40 @@ define('object',[], function() { return returnValue; }; - })(name, obj[name]); + })(obj, obj[name], proto[name]); obj[name].superInstalled = true; } }); } + /** + * Return the list of methods in `obj` that perform a supercall to `proto`. + * The list is cached in `klass`. + * + * `receiverName` is either "that" or "my". + */ + function methodsWithSuperCall(obj, proto, klass, receiverName) { + if (!klass.methodsWithSuperCall) { + Object.defineProperty(klass, "methodsWithSuperCall", { + enumerable: false, + writable: true, + value: {} + }); + } + + if (klass.methodsWithSuperCall[receiverName]) { + return klass.methodsWithSuperCall[receiverName]; + } + + klass.methodsWithSuperCall[receiverName] = Object.keys(obj).filter(function(name) { + return typeof(proto[name]) === "function" && + typeof(obj[name]) === "function" && + superCallRegex.test(obj[name]); + }); + + return klass.methodsWithSuperCall[receiverName]; + } + /** * Extend the class with new methods/properties. * @param{function} builder takes the same arguments as diff --git a/dist/klassified.min.js b/dist/klassified.min.js index 0f5c1d3..3bfe83a 100644 --- a/dist/klassified.min.js +++ b/dist/klassified.min.js @@ -3,4 +3,4 @@ * Released under MIT license, http://github.com/requirejs/almond/LICENSE */ -!function(e,n){"function"==typeof define&&define.amd?define(n):e.klassified=n(e.$)}(this,function(e){var n,t,s;return function(e){function r(e,n){return C.call(e,n)}function i(e,n){var t,s,r,i,c,o,u,a,f,l,p,b,h=n&&n.split("/"),d=m.map,g=d&&d["*"]||{};if(e){for(e=e.split("/"),c=e.length-1,m.nodeIdCompat&&A.test(e[c])&&(e[c]=e[c].replace(A,"")),"."===e[0].charAt(0)&&h&&(b=h.slice(0,h.length-1),e=b.concat(e)),f=0;f0&&(e.splice(f-1,2),f-=2)}e=e.join("/")}if((h||g)&&d){for(t=e.split("/"),f=t.length;f>0;f-=1){if(s=t.slice(0,f).join("/"),h)for(l=h.length;l>0;l-=1)if(r=d[h.slice(0,l).join("/")],r&&(r=r[s])){i=r,o=f;break}if(i)break;!u&&g&&g[s]&&(u=g[s],a=f)}!i&&u&&(i=u,o=a),i&&(t.splice(0,o,i),e=t.join("/"))}return e}function c(n,t){return function(){var s=j.call(arguments,0);return"string"!=typeof s[0]&&1===s.length&&s.push(null),h.apply(e,s.concat([n,t]))}}function o(e){return function(n){return i(n,e)}}function u(e){return function(n){E[e]=n}}function a(n){if(r(v,n)){var t=v[n];delete v[n],y[n]=!0,b.apply(e,t)}if(!r(E,n)&&!r(y,n))throw new Error("No "+n);return E[n]}function f(e){var n,t=e?e.indexOf("!"):-1;return t>-1&&(n=e.substring(0,t),e=e.substring(t+1,e.length)),[n,e]}function l(e){return e?f(e):[]}function p(e){return function(){return m&&m.config&&m.config[e]||{}}}var b,h,d,g,E={},v={},m={},y={},C=Object.prototype.hasOwnProperty,j=[].slice,A=/\.js$/;d=function(e,n){var t,s=f(e),r=s[0],c=n[1];return e=s[1],r&&(r=i(r,c),t=a(r)),r?e=t&&t.normalize?t.normalize(e,o(c)):i(e,c):(e=i(e,c),s=f(e),r=s[0],e=s[1],r&&(t=a(r))),{f:r?r+"!"+e:e,n:e,pr:r,p:t}},g={require:function(e){return c(e)},exports:function(e){var n=E[e];return"undefined"!=typeof n?n:E[e]={}},module:function(e){return{id:e,uri:"",exports:E[e],config:p(e)}}},b=function(n,t,s,i){var o,f,p,b,h,m,C,j=[],A=typeof s;if(i=i||n,m=l(i),"undefined"===A||"function"===A){for(t=!t.length&&s.length?["require","exports","module"]:t,h=0;h0&&(e.splice(f-1,2),f-=2)}e=e.join("/")}if((h||g)&&d){for(t=e.split("/"),f=t.length;f>0;f-=1){if(s=t.slice(0,f).join("/"),h)for(l=h.length;l>0;l-=1)if(r=d[h.slice(0,l).join("/")],r&&(r=r[s])){i=r,o=f;break}if(i)break;!u&&g&&g[s]&&(u=g[s],a=f)}!i&&u&&(i=u,o=a),i&&(t.splice(0,o,i),e=t.join("/"))}return e}function c(n,t){return function(){var s=S.call(arguments,0);return"string"!=typeof s[0]&&1===s.length&&s.push(null),h.apply(e,s.concat([n,t]))}}function o(e){return function(n){return i(n,e)}}function u(e){return function(n){E[e]=n}}function a(n){if(r(v,n)){var t=v[n];delete v[n],y[n]=!0,b.apply(e,t)}if(!r(E,n)&&!r(y,n))throw new Error("No "+n);return E[n]}function f(e){var n,t=e?e.indexOf("!"):-1;return t>-1&&(n=e.substring(0,t),e=e.substring(t+1,e.length)),[n,e]}function l(e){return e?f(e):[]}function p(e){return function(){return m&&m.config&&m.config[e]||{}}}var b,h,d,g,E={},v={},m={},y={},C=Object.prototype.hasOwnProperty,S=[].slice,j=/\.js$/;d=function(e,n){var t,s=f(e),r=s[0],c=n[1];return e=s[1],r&&(r=i(r,c),t=a(r)),r?e=t&&t.normalize?t.normalize(e,o(c)):i(e,c):(e=i(e,c),s=f(e),r=s[0],e=s[1],r&&(t=a(r))),{f:r?r+"!"+e:e,n:e,pr:r,p:t}},g={require:function(e){return c(e)},exports:function(e){var n=E[e];return"undefined"!=typeof n?n:E[e]={}},module:function(e){return{id:e,uri:"",exports:E[e],config:p(e)}}},b=function(n,t,s,i){var o,f,p,b,h,m,C,S=[],j=typeof s;if(i=i||n,m=l(i),"undefined"===j||"function"===j){for(t=!t.length&&s.length?["require","exports","module"]:t,h=0;h