Browse Source

Allow method late-binding with `instantiateFn`.

Herby Vojčík 2 months ago
parent
commit
7d55d42f70
3 changed files with 18 additions and 4 deletions
  1. 14 1
      lang/base/kernel-fundamentals.js
  2. 1 1
      lang/base/kernel-language.js
  3. 3 2
      lang/base/kernel-runtime.js

+ 14 - 1
lang/base/kernel-fundamentals.js

@@ -13,6 +13,13 @@ define(function () {
         return child;
     }
 
+    function defineMethod (klass, name, method) {
+        Object.defineProperty(klass.prototype, name, {
+            value: method,
+            enumerable: false, configurable: true, writable: true
+        });
+    }
+
     function SmalltalkGlobalsBrik (brikz, st) {
         var globals = Object.create(global);
         globals.SmalltalkSettings = {};
@@ -134,10 +141,15 @@ define(function () {
 
         coreFns.CompiledMethod = inherits(SmalltalkMethod, SmalltalkObject);
 
+        // fallback
+        defineMethod(SmalltalkMethod, "instantiateFn", function () {
+            return this.fn;
+        });
+
         /* Smalltalk method object. To add a method to a class,
          use api.addMethod() */
 
-        st.method = function (spec) {
+        st.method = function (spec, factory) {
             var that = new SmalltalkMethod();
             that.selector = spec.selector;
             that.args = spec.args || [];
@@ -148,6 +160,7 @@ define(function () {
             // TODO remove .referencedClasses, have .referencedGlobals
             that.referencedClasses = spec.referencedClasses || [];
             that.fn = spec.fn;
+            if (factory) that.instantiateFn = factory;
             return that;
         };
 

+ 1 - 1
lang/base/kernel-language.js

@@ -92,7 +92,7 @@ define(function () {
         var removeElement = brikz.arraySet.removeElement;
 
         function aliased (selector, method) {
-            var result = st.method(method);
+            var result = st.method(method, method.instantiateFn);
             if (method.selector !== selector) {
                 result.selector = selector;
                 result.source = '"Aliased as ' + selector + '"\n' + method.source;

+ 3 - 2
lang/base/kernel-runtime.js

@@ -170,9 +170,10 @@ define(function () {
         }
     }
 
-    RuntimeMethodsBrik.deps = ["event", "selectorConversion"];
+    RuntimeMethodsBrik.deps = ["event", "smalltalkGlobals", "selectorConversion"];
     function RuntimeMethodsBrik (brikz, st) {
         var st2js = brikz.selectorConversion.st2js;
+        var globals = brikz.smalltalkGlobals.globals;
         var emit = brikz.event.emit;
 
         function installMethod (method, klass) {
@@ -180,7 +181,7 @@ define(function () {
             if (!jsSelector) {
                 jsSelector = method.jsSelector = st2js(method.selector);
             }
-            installJSMethod(klass.fn.prototype, jsSelector, method.fn);
+            installJSMethod(klass.fn.prototype, jsSelector, method.instantiateFn(klass, globals));
         }
 
         this.installMethod = installMethod;