In a very specific constellation, pas2js produces javascript code that runs in the wrong scope. When the example below is run, the code jumps as expected into SomeProc, but instead of being there in the scope of the form data, erratically the program stays in the scope of the record FRec!
interface
type
TMyRec = Record
FFoo : Integer;
FProc : TProc;
End;
type
TForm4 = class(TWebForm)
WebEdit1: TWebEdit;
procedure WebFormShow(Sender: TObject);
private
FRec : TMyRec;
FBar : Integer;
procedure SetProc(P : TProc);
procedure SomeProc;
public
end;
implementation
procedure TForm4.SetProc(P: TProc);
begin
FRec.FFoo := 42;
FRec.FProc := P;
end;
procedure TForm4.SomeProc;
begin
WebEdit1.Text := 'bar';
end;
procedure TForm4.WebFormShow(Sender: TObject);
begin
SetProc(Self.SomeProc);
FRec.FProc;
end;
end.
This is what the browser debugger shows on entering SomeProc:
The reference to the scope data is '<this>'
(in the right pane). The content of '<this>'
should be the data of the form. We should see FRec and FBar and tons of other stuff listed there. Instead we see FFoo and FProc, which is the data scope of the record FRec. Hence, the next program step that says WebEdit1.Text := 'bar';
produces a runtime error TypeError: this.WebEdit1 is undefined
because WebEdit1 is erroneously out of scope.
This erratic behaviour does not happen if the call to SetProc() is omitted and, in writing FRec.FProc := Self.SomeProc
, the reference is stored directly. Also this does not happen if instead of the standard Delphi way SetProc(Self.SomeProc);
the address operator is used: SetProc(@SomeProc);
This was extremely difficult to reproduce and caused me again half a day of error hunting! You might want to pass this over to the pas2js guys.