mirror of
https://gitlab.com/freepascal.org/fpc/pas2js.git
synced 2025-09-13 11:49:06 +02:00
wasmjob: added demo to create a button with a click event
This commit is contained in:
parent
0303bf9da9
commit
211f4021eb
1
demo/wasienv/button/.gitignore
vendored
Normal file
1
demo/wasienv/button/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
lib
|
103
demo/wasienv/button/BrowserButton1.lpi
Normal file
103
demo/wasienv/button/BrowserButton1.lpi
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<Version Value="12"/>
|
||||||
|
<General>
|
||||||
|
<Flags>
|
||||||
|
<MainUnitHasCreateFormStatements Value="False"/>
|
||||||
|
<MainUnitHasTitleStatement Value="False"/>
|
||||||
|
<MainUnitHasScaledStatement Value="False"/>
|
||||||
|
<Runnable Value="False"/>
|
||||||
|
</Flags>
|
||||||
|
<SessionStorage Value="InProjectDir"/>
|
||||||
|
<Title Value="BrowserButton1"/>
|
||||||
|
<UseAppBundle Value="False"/>
|
||||||
|
<ResourceType Value="res"/>
|
||||||
|
</General>
|
||||||
|
<CustomData Count="4">
|
||||||
|
<Item0 Name="MaintainHTML" Value="1"/>
|
||||||
|
<Item1 Name="Pas2JSProject" Value="1"/>
|
||||||
|
<Item2 Name="PasJSLocation" Value="BrowserButton1"/>
|
||||||
|
<Item3 Name="PasJSWebBrowserProject" Value="1"/>
|
||||||
|
</CustomData>
|
||||||
|
<BuildModes>
|
||||||
|
<Item Name="Default" Default="True"/>
|
||||||
|
</BuildModes>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<UseFileFilters Value="True"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<FormatVersion Value="2"/>
|
||||||
|
</RunParams>
|
||||||
|
<Units>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="BrowserButton1.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="../button/index.html"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<CustomData Count="1">
|
||||||
|
<Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
|
||||||
|
</CustomData>
|
||||||
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="../dom/job_browser.pp"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="JOB_Browser"/>
|
||||||
|
</Unit>
|
||||||
|
</Units>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="11"/>
|
||||||
|
<Target FileExt=".js">
|
||||||
|
<Filename Value="BrowserButton1"/>
|
||||||
|
</Target>
|
||||||
|
<SearchPaths>
|
||||||
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<OtherUnitFiles Value="../dom"/>
|
||||||
|
<UnitOutputDirectory Value="js"/>
|
||||||
|
</SearchPaths>
|
||||||
|
<Parsing>
|
||||||
|
<SyntaxOptions>
|
||||||
|
<AllowLabel Value="False"/>
|
||||||
|
<CPPInline Value="False"/>
|
||||||
|
<UseAnsiStrings Value="False"/>
|
||||||
|
</SyntaxOptions>
|
||||||
|
</Parsing>
|
||||||
|
<CodeGeneration>
|
||||||
|
<TargetOS Value="browser"/>
|
||||||
|
</CodeGeneration>
|
||||||
|
<Linking>
|
||||||
|
<Debugging>
|
||||||
|
<GenerateDebugInfo Value="False"/>
|
||||||
|
<UseLineInfoUnit Value="False"/>
|
||||||
|
</Debugging>
|
||||||
|
</Linking>
|
||||||
|
<Other>
|
||||||
|
<CustomOptions Value="-Jeutf-8
|
||||||
|
-Jirtl.js
|
||||||
|
-Jc
|
||||||
|
-Jminclude
|
||||||
|
-dVerboseJOB"/>
|
||||||
|
<OtherDefines Count="1">
|
||||||
|
<Define0 Value="VerboseJOB"/>
|
||||||
|
</OtherDefines>
|
||||||
|
<CompilerPath Value="$(pas2js)"/>
|
||||||
|
</Other>
|
||||||
|
</CompilerOptions>
|
||||||
|
<Debugging>
|
||||||
|
<Exceptions>
|
||||||
|
<Item>
|
||||||
|
<Name Value="EAbort"/>
|
||||||
|
</Item>
|
||||||
|
<Item>
|
||||||
|
<Name Value="ECodetoolError"/>
|
||||||
|
</Item>
|
||||||
|
<Item>
|
||||||
|
<Name Value="EFOpenError"/>
|
||||||
|
</Item>
|
||||||
|
</Exceptions>
|
||||||
|
</Debugging>
|
||||||
|
</CONFIG>
|
127
demo/wasienv/button/BrowserButton1.lpr
Normal file
127
demo/wasienv/button/BrowserButton1.lpr
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
program BrowserButton1;
|
||||||
|
|
||||||
|
{$mode objfpc}
|
||||||
|
|
||||||
|
uses
|
||||||
|
BrowserConsole, BrowserApp, JS, Classes, SysUtils, Web, WebAssembly, Types,
|
||||||
|
WasiEnv, JOB_Browser, JOB_Shared;
|
||||||
|
|
||||||
|
Type
|
||||||
|
|
||||||
|
{ TMyApplication }
|
||||||
|
|
||||||
|
TMyApplication = class(TBrowserApplication)
|
||||||
|
// todo: most of this code should be moved a TBrowserJOBApplication
|
||||||
|
Private
|
||||||
|
FWasiEnv: TPas2JSWASIEnvironment;
|
||||||
|
FMemory : TJSWebAssemblyMemory; // Memory of webassembly
|
||||||
|
FTable : TJSWebAssemblyTable; // Table of exported functions
|
||||||
|
FWADomBridge : TJSObjectBridge;
|
||||||
|
function CreateWebAssembly(Path: string; ImportObject: TJSObject
|
||||||
|
): TJSPromise;
|
||||||
|
procedure DoWrite(Sender: TObject; const aOutput: String);
|
||||||
|
function InitEnv(aValue: JSValue): JSValue;
|
||||||
|
procedure InitWebAssembly;
|
||||||
|
Public
|
||||||
|
Constructor Create(aOwner : TComponent); override;
|
||||||
|
Destructor Destroy; override;
|
||||||
|
procedure DoRun; override;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMyApplication.InitEnv(aValue: JSValue): JSValue;
|
||||||
|
Var
|
||||||
|
Module : TJSInstantiateResult absolute aValue;
|
||||||
|
Exps : TWASIExports;
|
||||||
|
InitFunc: TProc;
|
||||||
|
begin
|
||||||
|
Result:=True;
|
||||||
|
FWasiEnv.Instance:=Module.Instance;
|
||||||
|
Exps := TWASIExports(TJSObject(Module.Instance.exports_));
|
||||||
|
//writeln('TMyApplication.InitEnv wasm exports=',TJSObject.keys(Exps));
|
||||||
|
FWADomBridge.WasiExports:=Exps;
|
||||||
|
|
||||||
|
// init the library
|
||||||
|
InitFunc:=TProc(Exps.functions['_initialize']);
|
||||||
|
writeln('TMyApplication.InitEnv ');
|
||||||
|
InitFunc();
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TMyApplication }
|
||||||
|
|
||||||
|
procedure TMyApplication.DoWrite(Sender: TObject; const aOutput: String);
|
||||||
|
begin
|
||||||
|
Writeln(aOutput);
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TMyApplication.Create(aOwner: TComponent);
|
||||||
|
begin
|
||||||
|
inherited Create(aOwner);
|
||||||
|
FWasiEnv:=TPas2JSWASIEnvironment.Create;
|
||||||
|
FWasiEnv.OnStdErrorWrite:=@DoWrite;
|
||||||
|
FWasiEnv.OnStdOutputWrite:=@DoWrite;
|
||||||
|
FWADomBridge:=TJSObjectBridge.Create(FWasiEnv);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMyApplication.CreateWebAssembly(Path: string; ImportObject: TJSObject): TJSPromise;
|
||||||
|
begin
|
||||||
|
Result:=window.fetch(Path)._then(Function (res : jsValue) : JSValue
|
||||||
|
begin
|
||||||
|
Result:=TJSResponse(Res).arrayBuffer._then(Function (res2 : jsValue) : JSValue
|
||||||
|
begin
|
||||||
|
Result:=TJSWebAssembly.instantiate(TJSArrayBuffer(res2),ImportObject);
|
||||||
|
end,Nil)
|
||||||
|
end,Nil
|
||||||
|
);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyApplication.InitWebAssembly;
|
||||||
|
|
||||||
|
Var
|
||||||
|
mDesc: TJSWebAssemblyMemoryDescriptor;
|
||||||
|
tDesc: TJSWebAssemblyTableDescriptor;
|
||||||
|
ImportObj : TJSObject;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// Setup memory
|
||||||
|
mDesc.initial:=256;
|
||||||
|
mDesc.maximum:=256;
|
||||||
|
FMemory:=TJSWebAssemblyMemory.New(mDesc);
|
||||||
|
// Setup table
|
||||||
|
tDesc.initial:=0;
|
||||||
|
tDesc.maximum:=0;
|
||||||
|
tDesc.element:='anyfunc';
|
||||||
|
FTable:=TJSWebAssemblyTable.New(tDesc);
|
||||||
|
// Setup ImportObject
|
||||||
|
ImportObj:=new([
|
||||||
|
'js', new([
|
||||||
|
'mem', FMemory,
|
||||||
|
'tbl', FTable
|
||||||
|
])
|
||||||
|
]);
|
||||||
|
FWasiEnv.AddImports(ImportObj);
|
||||||
|
CreateWebAssembly('WasiButton1.wasm',ImportObj)._then(@InitEnv);
|
||||||
|
end;
|
||||||
|
|
||||||
|
destructor TMyApplication.Destroy;
|
||||||
|
begin
|
||||||
|
FreeAndNil(FWasiEnv);
|
||||||
|
inherited Destroy;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TMyApplication.DoRun;
|
||||||
|
|
||||||
|
begin
|
||||||
|
// Your code here
|
||||||
|
Terminate;
|
||||||
|
InitWebAssembly;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
Application : TMyApplication;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Application:=TMyApplication.Create(nil);
|
||||||
|
Application.Initialize;
|
||||||
|
Application.Run;
|
||||||
|
end.
|
||||||
|
|
7
demo/wasienv/button/README.txt
Normal file
7
demo/wasienv/button/README.txt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Demo showing how to create a button from Wasi using JOB (JavaScript Object Bridge).
|
||||||
|
|
||||||
|
It contains the two projects
|
||||||
|
|
||||||
|
WasiButton1.lpi - Wasi
|
||||||
|
BrowserButton1.lpi - JavaScript/Pas2js
|
||||||
|
|
90
demo/wasienv/button/WasiButton1.lpi
Normal file
90
demo/wasienv/button/WasiButton1.lpi
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<CONFIG>
|
||||||
|
<ProjectOptions>
|
||||||
|
<Version Value="12"/>
|
||||||
|
<General>
|
||||||
|
<Flags>
|
||||||
|
<MainUnitHasCreateFormStatements Value="False"/>
|
||||||
|
<MainUnitHasTitleStatement Value="False"/>
|
||||||
|
<MainUnitHasScaledStatement Value="False"/>
|
||||||
|
</Flags>
|
||||||
|
<SessionStorage Value="InProjectDir"/>
|
||||||
|
<Title Value="WasiButton1"/>
|
||||||
|
<UseAppBundle Value="False"/>
|
||||||
|
<ResourceType Value="res"/>
|
||||||
|
</General>
|
||||||
|
<BuildModes>
|
||||||
|
<Item Name="Default" Default="True"/>
|
||||||
|
</BuildModes>
|
||||||
|
<PublishOptions>
|
||||||
|
<Version Value="2"/>
|
||||||
|
<UseFileFilters Value="True"/>
|
||||||
|
</PublishOptions>
|
||||||
|
<RunParams>
|
||||||
|
<FormatVersion Value="2"/>
|
||||||
|
</RunParams>
|
||||||
|
<Units>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="WasiButton1.lpr"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="../dom/job_wasm.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="JOB_WAsm"/>
|
||||||
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="../dom/job_web.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="JOB_Web"/>
|
||||||
|
</Unit>
|
||||||
|
<Unit>
|
||||||
|
<Filename Value="../dom/job_js.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
<UnitName Value="JOB_JS"/>
|
||||||
|
</Unit>
|
||||||
|
</Units>
|
||||||
|
</ProjectOptions>
|
||||||
|
<CompilerOptions>
|
||||||
|
<Version Value="11"/>
|
||||||
|
<Target>
|
||||||
|
<Filename Value="WasiButton1.wasm" ApplyConventions="False"/>
|
||||||
|
</Target>
|
||||||
|
<SearchPaths>
|
||||||
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<OtherUnitFiles Value="../dom"/>
|
||||||
|
<UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
|
||||||
|
</SearchPaths>
|
||||||
|
<CodeGeneration>
|
||||||
|
<TargetCPU Value="wasm32"/>
|
||||||
|
<TargetOS Value="wasi"/>
|
||||||
|
</CodeGeneration>
|
||||||
|
<Linking>
|
||||||
|
<Debugging>
|
||||||
|
<GenerateDebugInfo Value="False"/>
|
||||||
|
</Debugging>
|
||||||
|
<Options>
|
||||||
|
<ExecutableType Value="Library"/>
|
||||||
|
</Options>
|
||||||
|
</Linking>
|
||||||
|
<Other>
|
||||||
|
<OtherDefines Count="1">
|
||||||
|
<Define0 Value="VerboseInvokeJSArgs"/>
|
||||||
|
</OtherDefines>
|
||||||
|
<CompilerPath Value="/usr/lib/fpc/3.3.1/ppcrosswasm32"/>
|
||||||
|
</Other>
|
||||||
|
</CompilerOptions>
|
||||||
|
<Debugging>
|
||||||
|
<Exceptions>
|
||||||
|
<Item>
|
||||||
|
<Name Value="EAbort"/>
|
||||||
|
</Item>
|
||||||
|
<Item>
|
||||||
|
<Name Value="ECodetoolError"/>
|
||||||
|
</Item>
|
||||||
|
<Item>
|
||||||
|
<Name Value="EFOpenError"/>
|
||||||
|
</Item>
|
||||||
|
</Exceptions>
|
||||||
|
</Debugging>
|
||||||
|
</CONFIG>
|
73
demo/wasienv/button/WasiButton1.lpr
Normal file
73
demo/wasienv/button/WasiButton1.lpr
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
library WasiButton1;
|
||||||
|
|
||||||
|
{$mode objfpc}
|
||||||
|
{$h+}
|
||||||
|
{$codepage UTF8}
|
||||||
|
|
||||||
|
uses
|
||||||
|
SysUtils, JOB_WAsm, JOB_Shared, JOB_Web, JOB_JS;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TWasmApp }
|
||||||
|
|
||||||
|
TWasmApp = class
|
||||||
|
private
|
||||||
|
function OnButtonClick(Event: IJSEventListenerEvent): boolean;
|
||||||
|
public
|
||||||
|
procedure Run;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ TApplication }
|
||||||
|
|
||||||
|
function TWasmApp.OnButtonClick(Event: IJSEventListenerEvent): boolean;
|
||||||
|
begin
|
||||||
|
writeln('TWasmApp.OnButtonClick ');
|
||||||
|
if Event=nil then ;
|
||||||
|
|
||||||
|
JSWindow.Alert('You triggered TWasmApp.OnButtonClick');
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TWasmApp.Run;
|
||||||
|
var
|
||||||
|
JSDiv: IJSHTMLDivElement;
|
||||||
|
JSButton: IJSHTMLButtonElement;
|
||||||
|
begin
|
||||||
|
writeln('TWasmApp.Run getElementById "playground" ...');
|
||||||
|
// get reference of HTML element "playground" and type cast it to Div
|
||||||
|
JSDiv:=TJSHTMLDivElement.Cast(JSDocument.getElementById('playground'));
|
||||||
|
|
||||||
|
// create button
|
||||||
|
writeln('TWasmApp.Run create button ...');
|
||||||
|
JSButton:=TJSHTMLButtonElement.Cast(JSDocument.createElement('button'));
|
||||||
|
writeln('TWasmApp.Run set button caption ...');
|
||||||
|
JSButton.InnerHTML:='Click me!';
|
||||||
|
|
||||||
|
// add button to div
|
||||||
|
writeln('TWasmApp.Run add button to div ...');
|
||||||
|
JSDiv.append(JSButton);
|
||||||
|
|
||||||
|
// add event listener OnButtonClick
|
||||||
|
writeln('TWasmApp.Run addEventListener OnButtonClick ...');
|
||||||
|
JSButton.addEventListener('click',@OnButtonClick);
|
||||||
|
|
||||||
|
writeln('TWasmApp.Run END');
|
||||||
|
end;
|
||||||
|
|
||||||
|
// workaround: fpc wasm does not yet support exporting functions from units
|
||||||
|
function JOBCallback(const Func: TJOBCallback; Data, Code: Pointer; Args: PByte): PByte;
|
||||||
|
begin
|
||||||
|
Result:=JOB_WAsm.JOBCallback(Func,Data,Code,Args);
|
||||||
|
end;
|
||||||
|
|
||||||
|
exports
|
||||||
|
JOBCallback;
|
||||||
|
|
||||||
|
var
|
||||||
|
Application: TWasmApp;
|
||||||
|
begin
|
||||||
|
Application:=TWasmApp.Create;
|
||||||
|
Application.Run;
|
||||||
|
end.
|
||||||
|
|
1
demo/wasienv/button/bulma.min.css
vendored
Normal file
1
demo/wasienv/button/bulma.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
52
demo/wasienv/button/index.html
Normal file
52
demo/wasienv/button/index.html
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
|
||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>FPC-Webassembly Demo creating a button via JOB</title>
|
||||||
|
<link href="bulma.min.css" rel="stylesheet">
|
||||||
|
<script src="BrowserButton1.js"></script>
|
||||||
|
<style>
|
||||||
|
|
||||||
|
.source {
|
||||||
|
/* width: 730px; */
|
||||||
|
margin: -45px auto;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.source-inner {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
/* width: 482px; */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="section py-4">
|
||||||
|
<h1 class="title is-3">Test Area</h1>
|
||||||
|
<div class="box" id="playground">Playground</div>
|
||||||
|
</div>
|
||||||
|
<div class="section py-4">
|
||||||
|
<h1 class="title is-3">Console output</h1>
|
||||||
|
<div class="box" id="pasjsconsole"></div>
|
||||||
|
</div>
|
||||||
|
<!-- <hr> -->
|
||||||
|
<div class="section">
|
||||||
|
<div class="source">
|
||||||
|
<div class="source-inner">
|
||||||
|
<div>
|
||||||
|
<p>Created using <a target="_blank" href="https://wiki.freepascal.org/pas2js">pas2js.</a> </p>
|
||||||
|
<p>Pas2JS Sources: <a target="new" href="BrowserButton1.lpr">Pas2JS Program</a></p>
|
||||||
|
<p>Webassembly Sources: <a target="new" href="WasiButton1.lpr">FPC Program</a></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
rtl.showUncaughtExceptions=true;
|
||||||
|
rtl.run();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user