Morfik Tip: Calling Morfik functions or methods from JavaScript
March 9, 2007From time to time you will want to drop to JavaScript to perform various operations (like when you use a third-party JavaScript library). In those cases you may want to call a Morfik function or method. How can it be done?
Let’s see first how Morfik functions (and procedures) can be called:
function AFunctionToCall(x, y: Integer; s: String) : Integer; ['Obfuscate=false']; Begin Result := x+y; End; Procedure DefeatTheOptimizer; // Make sure you call THIS procedure somewhere // (e.g. in FormReady, or in Initialization) Begin Exit; // call all functions here that you don’t // want the optimizer to eliminate AFunctionToCall(0,0,””); End; function GetFuncResult: Integer; JavaScript; (*! return AFunctionToCall(34, 26, “hello”); *)
Very simple. Arman Mirkazemi has a few instructions, though:
It is possible to call Morfik functions from JavaScript. You need to make sure that the compiler does not obfuscate the function name by placing a compiler tag ['Obfuscate=false']; in front of your function declaration.
Secondly, the JavaScript optimizer is designed to remove code that does not get called anywhere in the application. When turned on, the JavaScript optimizer produces a lighter weight JavaScript code to send to the browser.
To stop the optimizer from taking your function out you must call it from another Function. In this case your application may not need to call “myMorfikFunction” anywhere, thus to get around that you could call it from one of your methods after an Exit; statement.
OK. Now let’s see Morfik methods. They are a bit different, since you have to make sure that self/this is set up properly:
Type
TTestClass = Class(TObject)
s: String;
i: Integer;
f: Double;
constructor Create;
function GetIMultipliedBy(x, y, z: Integer): Integer;
end; ['Obfuscate=false'];
constructor TTestClass.Create;
begin
s := ‘apple’;
i := 42;
f := 3.1415926;
end;
function TTestClass.GetIMultipliedBy(x, y, z: Integer): Integer;
begin
Result := i * x * y * z;
end;
function GetMethodResult(p: Pointer): Integer; JavaScript; (*!
return p(2,10,100);
*)
function getSimpleMethodPointer(o,m: Pointer): Pointer; JavaScript; (*!
if(m)
return function(){
return m.apply(o, arguments);
}
else
return null;
*)
Procedure Index.ButtonTestClick(Event: TDOMEvent);
Var
tc: TTestClass;
s: String;
Begin
salamon := ‘hello world’;
tc := TTestClass.Create;
s := tc.s + ”;
s := s + TJObject(tc).toString + ”;
s := s + tc.ClassName + ”;
s := s + IntToStr(GetMethodResult(
getSimpleMethodPointer(tc, @tc.GetIMultipliedBy)
));
tlTC.Caption := s;
End;
The tricky part is getSimpleMethodPointer(). It will return a pointer to the method instance (technically it creates an anonymous function that calls the function on the class with all the parameters it was called with). Please note that there is a similar Morfik function called getMethodPointer(), but that does not handle multiple parameters at the moment and is also fiddling with the bandindex that takes CPU cycles, so I prefer to use this one, if I know I’m not on a continuous form. And it cannot work on normal functions or class methods either (see later).
BTW with this solution you do not need to turn off Obfuscation, since you will pass the actual (obfuscated) name of the object and method to the function at runtime, as opposed to the previous function call, where the compiler will not replace inside the JavaScript routine the name of the Morfik function with the obfuscated version (wow! Simple, is it!?;-). So you could do a similar trick with non-method functions by doing this: getSimpleMethodPointer(Nil, AFunctionToCall); This would also eliminate the need for the DefeatTheOptimizer function, since you do refer to the function-to-be-called-from-JavaScript, so the optimizer will not eliminate it. Of course, you have to alter the JavaScript function to take the function-to-be-called-from-JavaScript as a parameter. You can call class methods (ones that don’t need an instance) the same way, by passing Nil as the first parameter.
Update - getSimpleMethodPointer() explanation
It turned out that I skipped some details on the parameters of getSimpleMethodPointer(), so let’s remedy that now:
- o is an object instance (address) upon which you want to call the method and
- m is the method (address) of the object you want to call (always use the address-of (@) operator to play on the safe side).
First this seems straightforward, but! Let’s see a confusing example:
procedure AJavaScriptFunction(s : string; cb: pointer); JavaScript; (*!
cb(s);
*)
procedure Index.CallTheJavaScriptFunction;
begin
AJavaScriptFunction('Morfik rulez', getSimpleMethodPointer(Self, @SendMessage));
end;
procedure Index.SendMessage(sMsg: String); begin ... end;
The important part is the getSimpleMethodPointer() call’s first parameter: Self. One could first simply put Index instead of Self here, but that would be wrong. Why? because Index represents the class (technically it will become (the name of) a JavaScript constructor function) and we need instead an object instance here, which in our case is stored in Self. That’s why in my original example I used tc (which is an object instance) instead of TTestClass (which is the class). Hope this helps…
BTW (for Delphi chaps) it would be more prudent to use the semi-Hungarian naming convention for forms, because then Index would be called TIndex, and no one would mistake it for an instance variable (Var Index: TIndex, anyone?). Aren’t all good things invented by Hungarians? ;-) Quiz question: why is it called the Hungarian naming convention?
One word on the address-of operator (@): if the function does have parameters then you don’t have to use it, because the compiler can tell that you want to get the address of the function, but if your function has no parameters, then (in Pascal) the compiler will guess that you want to call the function, and getSimpleMethodPointer() will get the return value of the function, which is not what we wanted. So play on the safe side and use the address-of operator.
Enjoy! Comments appreciated…

Wow, so now I can write complex logic in Pascal
Stoicho Monev | March 9, 2007Wow, so now I can write complex logic in Pascal or other 3 (Basic, Java and c#), and then I can expose this to JavaScript.
Until now, I did not have a scenario where I might use this, but I guess it is just because I did not know this exists.
Btw, I can not test this now, but is this the actual calling from javascript:
function GetFuncResult: Integer; JavaScript; (*!
return AFunctionToCall(34, 26, “hello”);
*)
If so, why the syntax is like that? I mean the ‘*’ and ‘!,’?
Hi Stoicho, You make a point here. The JavaScript example function
piprog | March 9, 2007Hi Stoicho,
You make a point here. The JavaScript example function I have shown is actually a JavaScript function embedded in Pascal :-) — I’ll write a new Tip clarifying this. But the essence is: you can copy the above function verbatim into a Pascal file, and it will work! Morfik rulez :-)
Peter
I updated the original post with some more info on
piprog | March 9, 2007I updated the original post with some more info on getSimpleMethodPointer().