Browse Source

* WASI runtime embedding

Michaël Van Canneyt 3 years ago
parent
commit
2626eef7c3

+ 22 - 0
demo/asyncawait/asyncawaitdemos.lpg

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="manualpromise.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="tryfetch.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="trymany.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+    </Targets>
+  </ProjectGroup>
+</CONFIG>

+ 87 - 70
demo/chartjs/chartjs_demos.lpg

@@ -1,75 +1,92 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
-  <ProjectGroup FileVersion="1">
-    <Targets Count="17">
-      <Target0 FileName="demoarea.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target0>
-      <Target1 FileName="demobar.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target1>
-      <Target2 FileName="demobubble.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target2>
-      <Target3 FileName="democustompoints.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target3>
-      <Target4 FileName="demodatalabelling.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target4>
-      <Target5 FileName="demodate.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target5>
-      <Target6 FileName="demodoughnut.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target6>
-      <Target7 FileName="demointeractions.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target7>
-      <Target8 FileName="demoline.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target8>
-      <Target9 FileName="demomixed.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target9>
-      <Target10 FileName="demopie.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target10>
-      <Target11 FileName="demopolararea.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target11>
-      <Target12 FileName="demoprogressbar.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target12>
-      <Target13 FileName="demoradar.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target13>
-      <Target14 FileName="demoscatter.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target14>
-      <Target15 FileName="demoscriptablebubble.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target15>
-      <Target16 FileName="demotime.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target16>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="demoarea.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demobar.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demobubble.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="democustompoints.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demodatalabelling.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demodate.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demodoughnut.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demointeractions.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demoline.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demomixed.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demopie.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demopolararea.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demoprogressbar.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demoradar.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demoscatter.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demoscriptablebubble.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="demotime.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
     </Targets>
   </ProjectGroup>
 </CONFIG>

+ 114 - 42
demo/pas2js_demos.lpg

@@ -1,47 +1,119 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
-  <ProjectGroup FileVersion="1">
-    <Targets Count="19">
-      <Target0 FileName="rtl/rtl_demos.lpg"/>
-      <Target1 FileName="promise/promise_demos.lpg"/>
-      <Target2 FileName="chartjs/chartjs_demos.lpg"/>
-      <Target3 FileName="webgl/webgl_demos.lpg"/>
-      <Target4 FileName="router/demorouter.lpi"/>
-      <Target5 FileName="router/demorouter2.lpi"/>
-      <Target6 FileName="trayicon/trayicon.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target6>
-      <Target7 FileName="dataabstract/sampleda.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target7>
-      <Target8 FileName="fcldb/demodb.lpi"/>
-      <Target9 FileName="fcldb/demoload.lpi"/>
-      <Target10 FileName="fcldb/demorest.lpi"/>
-      <Target11 FileName="fcldb/demorest2.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target11>
-      <Target12 FileName="fcldb/restserver.lpi"/>
-      <Target13 FileName="fpcunit/browsertest.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="default"/>
-      </Target13>
-      <Target14 FileName="dynload/testloader.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target14>
-      <Target15 FileName="hotreload/hotreload.lpi"/>
-      <Target16 FileName="hotreload/server.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target16>
-      <Target17 FileName="jquery/demoadd.lpi"/>
-      <Target18 FileName="jspdf/basic.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target18>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="rtl/rtl_demos.lpg"/>
+      <Target FileName="promise/promise_demos.lpg"/>
+      <Target FileName="chartjs/chartjs_demos.lpg"/>
+      <Target FileName="webgl/webgl_demos.lpg"/>
+      <Target FileName="asyncawait/asyncawaitdemos.lpg"/>
+      <Target FileName="wasienv/wasienvdemos.lpg"/>
+      <Target FileName="translate/translate_demos.lpg"/>
+      <Target FileName="resources/resourcedemos.lpg"/>
+      <Target FileName="router/demorouter.lpi">
+        <BuildModes>
+          <Mode Name="default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="router/demorouter2.lpi"/>
+      <Target FileName="dataabstract/sampleda.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="fcldb/demodb.lpi"/>
+      <Target FileName="fcldb/demoload.lpi"/>
+      <Target FileName="fcldb/demorest.lpi"/>
+      <Target FileName="fcldb/restserver.lpi"/>
+      <Target FileName="fpcunit/browsertest.lpi"/>
+      <Target FileName="dynload/testloader.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="hotreload/hotreload.lpi"/>
+      <Target FileName="hotreload/server.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="jquery/demoadd.lpi"/>
+      <Target FileName="jspdf/basic.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="fullcalendar/demofullcalendar.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="fullcalendar/demofullcalendar4.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="fullcalendar/demofullcalendar5.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="fpreport/reportdemo.lpi"/>
+      <Target FileName="jitsimeet/demojitsimeet.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="pushjs/helloworld.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="tetris/tetris.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="websockets/demowebsocket.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="webwidget/widgets/webwidgetsdemo.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="xterm/xtermdemo.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="restbridge/simple/restbridgeclient.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="opentok/demoopentok.lpi">
+        <BuildModes>
+          <Mode Name="default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="extend_jsclass/ExtendJSFunctionClass1.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="bootstrap/demobootstraptable.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="atom/pas2jsdemopackage.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
     </Targets>
   </ProjectGroup>
 </CONFIG>

+ 7 - 7
demo/promise/promise_demos.lpg

@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
-  <ProjectGroup FileVersion="1">
-    <Targets Count="5">
-      <Target0 FileName="story.lpi"/>
-      <Target1 FileName="story2.lpi"/>
-      <Target2 FileName="story3.lpi"/>
-      <Target3 FileName="demoall.lpi"/>
-      <Target4 FileName="askmom.lpi"/>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="story.lpi"/>
+      <Target FileName="story2.lpi"/>
+      <Target FileName="story3.lpi"/>
+      <Target FileName="demoall.lpi"/>
+      <Target FileName="askmom.lpi"/>
     </Targets>
   </ProjectGroup>
 </CONFIG>

+ 27 - 0
demo/resources/resourcedemos.lpg

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="consoledemo.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="htmldemo.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="htmllinkdemo.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="htmlloadlinkdemo.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+    </Targets>
+  </ProjectGroup>
+</CONFIG>

+ 20 - 16
demo/rtl/rtl_demos.lpg

@@ -1,21 +1,25 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
-  <ProjectGroup FileVersion="1">
-    <Targets Count="14">
-      <Target0 FileName="demoajax.lpi"/>
-      <Target1 FileName="demobrowserconsole.lpi"/>
-      <Target2 FileName="democanvas2d.lpi"/>
-      <Target3 FileName="democlasstopas.lpi"/>
-      <Target4 FileName="democollection.lpi"/>
-      <Target5 FileName="democomponents.lpi"/>
-      <Target6 FileName="demodatetime.lpi"/>
-      <Target7 FileName="demodombuttonevent.lpi"/>
-      <Target8 FileName="demojsarray.lpi"/>
-      <Target9 FileName="demorouter.lpi"/>
-      <Target10 FileName="demortti.lpi"/>
-      <Target11 FileName="demostringlist.lpi"/>
-      <Target12 FileName="demouncaughtexception.lpi"/>
-      <Target13 FileName="demoxhr.lpi"/>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="demoajax.lpi"/>
+      <Target FileName="demobrowserconsole.lpi"/>
+      <Target FileName="democanvas2d.lpi"/>
+      <Target FileName="democlasstopas.lpi">
+        <BuildModes>
+          <Mode Name="default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="democollection.lpi"/>
+      <Target FileName="democomponents.lpi"/>
+      <Target FileName="demodatetime.lpi"/>
+      <Target FileName="demodombuttonevent.lpi"/>
+      <Target FileName="demojsarray.lpi"/>
+      <Target FileName="demorouter.lpi"/>
+      <Target FileName="demortti.lpi"/>
+      <Target FileName="demostringlist.lpi"/>
+      <Target FileName="demouncaughtexception.lpi"/>
+      <Target FileName="demoxhr.lpi"/>
     </Targets>
   </ProjectGroup>
 </CONFIG>

+ 22 - 0
demo/translate/translate_demos.lpg

@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="translate_basic.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="translate_object.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="translate_url.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+    </Targets>
+  </ProjectGroup>
+</CONFIG>

+ 56 - 0
demo/wasienv/canvas/canvasdraw.lpi

@@ -0,0 +1,56 @@
+<?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="canvasdraw"/>
+      <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="canvasdraw.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="canvasdraw"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="lib/$(TargetCPU)-$(TargetOS)"/>
+    </SearchPaths>
+  </CompilerOptions>
+  <Debugging>
+    <Exceptions>
+      <Item>
+        <Name Value="EAbort"/>
+      </Item>
+      <Item>
+        <Name Value="ECodetoolError"/>
+      </Item>
+      <Item>
+        <Name Value="EFOpenError"/>
+      </Item>
+    </Exceptions>
+  </Debugging>
+</CONFIG>

+ 138 - 0
demo/wasienv/canvas/canvasdraw.lpr

@@ -0,0 +1,138 @@
+program canvasdraw;
+
+{$mode objfpc}
+{$h+}
+uses
+  sysutils, webcanvas;
+
+Type
+  ECanvas = class(Exception);
+
+  { TWebCanvas }
+
+  TWebCanvas = class(TObject)
+  private
+    FCanvasID : Longint;
+    FHeight: Longint;
+    FWidth: Longint;
+  Protected
+    Procedure Check(aError : TCanvasError; const aMsg : String = '');
+  Public
+    Constructor Create(aWidth,aHeight : Longint);
+    Procedure moveto(X : Longint;Y : Longint);
+    Procedure lineto(X : Longint; Y : Longint);
+    Procedure stroke();
+    Procedure beginpath();
+    Procedure arc(X : Longint;Y : Longint;Radius : Longint;StartAngle : Double;EndAngle : Double);
+    Procedure fillrect(X : Longint; Y : Longint;  Width : Longint; Height : Longint);
+    Procedure strokerect(X : Longint;Y : Longint; Width : Longint; Height : Longint);
+    Procedure clearrect(X : Longint;Y : Longint;Width : Longint; Height : Longint );
+    Procedure StrokeText(X : Longint;Y : Longint;S : UTF8String);
+    Procedure FillText(X : Longint;Y : Longint;S : UTF8String);
+    Property CanvasID : Integer Read FCanvasID;
+    Property Width : Longint Read FWidth;
+    Property Height : Longint Read FHeight;
+  end;
+
+{ TWebCanvas }
+
+procedure TWebCanvas.Check(aError: TCanvasError; const aMsg: String);
+begin
+  if aError<>ECANVAS_SUCCESS then
+    if aMsg='' then
+      Raise Exception.CreateFmt('Canvas Operation failed %d',[aError])
+    else
+      Raise Exception.CreateFmt('%s : Error code %d',[aMsg,aError]);
+
+end;
+
+constructor TWebCanvas.Create(aWidth, aHeight: Longint);
+begin
+  Check(__webcanvas_allocate(aWidth,aHeight,@FCanvasID),'Failed to create web canvas');
+  FWidth:=aWidth;
+  FHeight:=aHeight;
+end;
+
+procedure TWebCanvas.moveto(X: Longint; Y: Longint);
+begin
+  Check(__webcanvas_moveto(FCanvasID,X,Y));
+end;
+
+procedure TWebCanvas.lineto(X: Longint; Y: Longint);
+begin
+  Check(__webcanvas_lineto(FCanvasID,X,Y));
+end;
+
+procedure TWebCanvas.stroke;
+begin
+  Check(__webcanvas_stroke(FCanvasID));
+end;
+
+procedure TWebCanvas.beginpath;
+begin
+  Check(__webcanvas_beginpath(FCanvasID));
+end;
+
+procedure TWebCanvas.arc(X: Longint; Y: Longint; Radius: Longint;
+  StartAngle: Double; EndAngle: Double);
+begin
+  Check(__webcanvas_arc(FCanvasID,X,Y,Radius,StartAngle,EndAngle));
+end;
+
+procedure TWebCanvas.fillrect(X: Longint; Y: Longint; Width: Longint;
+  Height: Longint);
+begin
+  Check(__webcanvas_fillrect(FCanvasID,X,Y,Width,Height));
+end;
+
+procedure TWebCanvas.strokerect(X: Longint; Y: Longint; Width: Longint;
+  Height: Longint);
+begin
+  Check(__webcanvas_strokerect(FCanvasID,X,Y,Width,Height));
+end;
+
+procedure TWebCanvas.clearrect(X: Longint; Y: Longint; Width: Longint;
+  Height: Longint);
+begin
+  Check(__webcanvas_clearrect(FCanvasID,X,Y,Width,Height));
+end;
+
+procedure TWebCanvas.StrokeText(X: Longint; Y: Longint; S: UTF8String);
+begin
+  Check(__webcanvas_stroketext(FCanvasID,X,Y,PByte(PAnsichar(S)),Length(S)));
+end;
+
+procedure TWebCanvas.FillText(X: Longint; Y: Longint; S: UTF8String);
+begin
+  Check(__webcanvas_filltext(FCanvasID,X,Y,PByte(PAnsichar(S)),Length(S)));
+end;
+
+Var
+  aCanvas : TWebCanvas;
+
+begin
+  aCanvas:=TWebCanvas.Create(150,150);
+  With aCanvas do
+    try
+      Writeln('Filling rect');
+      fillRect(25, 25, 100, 100);
+      Writeln('Clearing rect');
+      clearRect(45, 45, 60, 60);
+      Writeln('Stroking rect');
+      strokeRect(50, 50, 50, 50);
+      Writeln('Drawing cross');
+      BeginPath;
+      MoveTo(25,25);
+      Writeln('First line');
+      LineTo(125,125);
+      MoveTo(125,25);
+      Writeln('Second line');
+      LineTo(25,125);
+      Stroke;
+      Writeln('Writing text');
+      FillText(8,8,'Greetings on the WebAssembly Canvas!');
+    finally
+      Free;
+    end;
+end.
+

+ 92 - 0
demo/wasienv/canvas/demowasicanvas.lpi

@@ -0,0 +1,92 @@
+<?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="demowasicanvas"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <CustomData Count="2">
+      <Item0 Name="MaintainHTML" Value="1"/>
+      <Item1 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="demowasicanvas.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+      <Unit>
+        <Filename Value="index.html"/>
+        <IsPartOfProject Value="True"/>
+        <CustomData Count="1">
+          <Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
+        </CustomData>
+      </Unit>
+      <Unit>
+        <Filename Value="wacanvas.pp"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target FileExt=".js">
+      <Filename Value="demowasicanvas"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <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"/>
+      <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>

+ 121 - 0
demo/wasienv/canvas/demowasicanvas.lpr

@@ -0,0 +1,121 @@
+program demowasicanvas;
+
+{$mode objfpc}
+
+uses
+  browserconsole, browserapp, JS, Classes, SysUtils, Web, WebAssembly, types, wasienv, wacanvas;
+
+Type
+
+  { TMyApplication }
+
+  TMyApplication = class(TBrowserApplication)
+  Private
+    FWasiEnv: TPas2JSWASIEnvironment;
+    FMemory : TJSWebAssemblyMemory; // Memory of webassembly
+    FTable : TJSWebAssemblyTable; // Table of exported functions
+    FWACanvas : TWACanvas; // canvas extension
+    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;
+
+begin
+  Result:=True;
+  Exps := TWASIExports(TJSObject(Module.Instance.exports_));
+  FWasiEnv.Instance:=Module.Instance;
+//  console.info('got exports', exps);
+  Exps.Start;
+end;
+
+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;
+  FWACanvas:=TWACanvas.Create(FWasiEnv);
+  FWACanvas.CanvasParent:=GetHTMLElement('canvases');
+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('canvasdraw.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.

+ 51 - 0
demo/wasienv/canvas/index.html

@@ -0,0 +1,51 @@
+<!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 and Pas2JS Demo</title>
+  <link href="bulma.min.css" rel="stylesheet">
+  <script src="demowasicanvas.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">
+    <h1 class="title is-3">Canvas</h1>
+    <div id="canvases"></div>
+  </div>
+  <div class="section">
+    <h1 class="title is-3">Console output</h1>
+    <div id="pasjsconsole"></div>
+  </div>
+  <hr>
+  <div class="section">
+    <div class="source">
+      <div class="source-inner">
+        <div>
+          <p>Created using &nbsp; <a target="_blank" href="https://wiki.freepascal.org/pas2js">pas2js.</a> </p>
+          <p>Pas2JS Sources: &nbsp; <a target="new" href="demowasicanvas.lpr">Pas2JS Program</a></p>
+          <p>Webassembly Sources: &nbsp; <a target="new" href="canvasdraw.lpr">FPC Program</a></p>
+        </div>
+      </div>
+    </div>
+  </div>
+  <script>
+    rtl.showUncaughtExceptions=true;
+    rtl.run();
+  </script>
+</body>
+</html>

+ 261 - 0
demo/wasienv/canvas/wacanvas.pp

@@ -0,0 +1,261 @@
+{$mode objfpc}
+{$h+}
+unit wacanvas;
+
+interface
+
+uses js, web, webassembly, wasienv;
+
+Const
+  ECANVAS_SUCCESS     = 0;
+  ECANVAS_NOCANVAS    = 1;
+  ECANVAS_UNSPECIFIED = -1;
+
+Type
+  TCanvasError = Longint;
+  TCanvasID = Longint;
+  
+  { TWACanvas }
+
+  TWACanvas = class(TImportExtension)
+  Private 
+    FCanvases : TJSObject;
+    FCurrentID : Integer;
+    FCanvasParent : TJSHTMLELement;
+  Protected
+    function GetCanvas(aID : TCanvasID) : TJSCanvasRenderingContext2D;
+    function allocate(SizeX : Longint; SizeY : Longint; aID: Longint): TCanvasError;   
+    function moveto(aID : TCanvasID; X : Longint;Y : Longint): TCanvasError;
+    function lineto(aID : TCanvasID;X : Longint; Y : Longint ):  TCanvasError; 
+    function stroke(aID : TCanvasID): TCanvasError; 
+    function beginpath(aID : TCanvasID):  TCanvasError; 
+    function arc(aID : TCanvasID;X : Longint;Y : Longint;Radius : Longint;StartAngle : Double;EndAngle : Double):  TCanvasError; 
+    function fillrect(aID : TCanvasID;  X : Longint; Y : Longint;  Width : Longint; Height : Longint): TCanvasError; 
+    function strokerect(aID : TCanvasID;X : Longint;Y : Longint; Width : Longint; Height : Longint ):  TCanvasError; 
+    function clearrect(aID : TCanvasID;X : Longint;Y : Longint;Width : Longint; Height : Longint ):  TCanvasError; 
+    function StrokeText(aID : TCanvasID;X : Longint;Y : Longint; aText : Longint; aTextLen : Longint ):  TCanvasError;
+    function FillText(aID : TCanvasID;X : Longint;Y : Longint; aText : Longint; aTextLen : Longint ):  TCanvasError;
+  Public
+    Constructor Create(aEnv : TPas2JSWASIEnvironment); override;
+    Procedure FillImportObject(aObject : TJSObject); override;
+    Function ImportName : String; override;
+    Property CanvasParent : TJSHTMLELement Read FCanvasParent Write FCanvasParent;
+  end;
+
+Implementation
+
+uses sysutils;
+
+constructor TWACanvas.Create(aEnv: TPas2JSWASIEnvironment);
+
+begin
+  Inherited Create(aEnv);
+  FCanvases:=TJSObject.New();
+end;
+
+function TWACanvas.ImportName: String;
+
+begin
+  Result:='web_canvas';
+end;
+
+
+function TWACanvas.GetCanvas(aID : TCanvasID) : TJSCanvasRenderingContext2D;
+
+Var
+  JS : JSValue;
+begin
+  JS:=FCanvases[IntTostr(AID)];
+  if IsObject(JS)  then
+    Result:=TJSCanvasRenderingContext2D(JS)
+  else
+    Result:=Nil;  
+end;
+
+procedure TWACanvas.FillImportObject(aObject: TJSObject);
+
+begin
+  aObject['allocate']:=@allocate;
+  aObject['moveto']:=@moveto;
+  aObject['lineto']:=@LineTo;
+  aObject['stroke']:=@stroke;
+  aObject['beginpath']:=@beginpath;
+  aObject['arc']:=@arc;
+  aObject['fillrect']:=@fillrect;
+  aObject['strokerect']:=@strokerect;
+  aObject['clearrect']:=@clearrect;
+  aObject['stroketext']:=@StrokeText;
+  aObject['filltext']:=@FillText;
+
+end;   
+
+function TWACanvas.allocate(SizeX : Longint; SizeY : Longint; aID: Longint): TCanvasError;   
+
+Var
+  C : TJSElement;
+  V : TJSDataView;
+  
+begin
+  C:=window.document.createElement('CANVAS');
+  CanvasParent.AppendChild(C);
+  Inc(FCurrentID);
+  V:=getModuleMemoryDataView; 
+  FCanvases[IntToStr(FCurrentID)]:=TJSHTMLCanvasElement(c).getcontext('2d');
+  v.setUint32(aID, FCurrentID, env.IsLittleEndian); 
+  Result:=ECANVAS_SUCCESS;
+end;
+
+function TWACanvas.moveto(aID : TCanvasID; X : Longint;Y : Longint): TCanvasError;
+
+Var
+  C : TJSCanvasRenderingContext2D;
+
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    C.moveto(X,Y);
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.lineto(aID : TCanvasID;X : Longint; Y : Longint ):  TCanvasError; 
+
+Var
+  C : TJSCanvasRenderingContext2D;
+
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    C.lineto(X,Y);
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.stroke(aID : TCanvasID): TCanvasError; 
+
+Var
+  C : TJSCanvasRenderingContext2D;
+
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    C.Stroke;
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.beginpath(aID : TCanvasID):  TCanvasError; 
+
+Var
+  C : TJSCanvasRenderingContext2D;
+
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    C.beginPath;
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.arc(aID : TCanvasID;X : Longint;Y : Longint;Radius : Longint;StartAngle : Double;EndAngle : Double):  TCanvasError; 
+
+Var
+  C : TJSCanvasRenderingContext2D;
+
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    C.arc(X,y,radius,Startangle,EndAngle);
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.fillrect(aID : TCanvasID;  X : Longint; Y : Longint;  Width : Longint; Height : Longint): TCanvasError; 
+
+Var
+  C : TJSCanvasRenderingContext2D;
+
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    C.FillRect(X,y,width,Height);
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.strokerect(aID : TCanvasID;X : Longint;Y : Longint; Width : Longint; Height : Longint ):  TCanvasError; 
+
+Var
+  C : TJSCanvasRenderingContext2D;
+
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    C.StrokeRect(X,Y,Width,Height);
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.clearrect(aID : TCanvasID;X : Longint;Y : Longint;Width : Longint; Height : Longint ):  TCanvasError; 
+
+Var
+  C : TJSCanvasRenderingContext2D;
+
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    C.ClearRect(X,Y,Width,Height);
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.StrokeText(aID: TCanvasID; X: Longint; Y: Longint;
+  aText: Longint; aTextLen: Longint): TCanvasError;
+
+Var
+  C : TJSCanvasRenderingContext2D;
+  S : String;
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    S:=Env.GetUTF8StringFromMem(aText,aTextLen);
+    C.StrokeText(S,X,Y);
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+function TWACanvas.FillText(aID: TCanvasID; X: Longint; Y: Longint;
+  aText: Longint; aTextLen: Longint): TCanvasError;
+Var
+  C : TJSCanvasRenderingContext2D;
+  S : String;
+begin
+  Result:=ECANVAS_NOCANVAS;
+  C:=GetCanvas(aID);
+  if Assigned(C) then
+    begin
+    S:=Env.GetUTF8StringFromMem(aText,aTextLen);
+    C.FillText(S,X,Y);
+    Result:=ECANVAS_SUCCESS;
+    end;
+end;
+
+end.  

+ 97 - 0
demo/wasienv/canvas/webcanvas.pp

@@ -0,0 +1,97 @@
+unit webcanvas;
+
+interface
+
+// These types and constants could go in a unit shared between pas2js and webassembly !
+
+Type
+  TCanvasError = longint;
+  TCanvasID = longint;
+  PCanvasID = ^TCanvasID;
+
+Const
+  ECANVAS_SUCCESS     = 0;
+  ECANVAS_NOCANVAS    = 1;
+  ECANVAS_UNSPECIFIED = -1;
+
+function __webcanvas_allocate(
+  SizeX : Longint;
+  SIzeY : Longint;
+  aID: PCanvasID
+): TCanvasError; external 'web_canvas' name 'allocate';
+
+function __webcanvas_moveto(
+  aID : TCanvasID;
+  X : Longint;
+  Y : Longint
+):  TCanvasError; external 'web_canvas' name 'moveto';
+
+function __webcanvas_lineto(
+  aID : TCanvasID;
+  X : Longint;
+  Y : Longint
+):  TCanvasError; external 'web_canvas' name 'lineto';
+
+function __webcanvas_stroke(
+  aID : TCanvasID
+):  TCanvasError; external 'web_canvas' name 'stroke';
+
+function __webcanvas_beginpath(
+  aID : TCanvasID
+):  TCanvasError; external 'web_canvas' name 'beginpath';
+
+function __webcanvas_arc(
+  aID : TCanvasID;
+  X : Longint;
+  Y : Longint;
+  Radius : Longint;
+  StartAngle : Double;
+  EndAngle : Double
+):  TCanvasError; external 'web_canvas' name 'arc';
+
+
+function __webcanvas_fillrect(
+  aID : TCanvasID;
+  X : Longint;
+  Y : Longint;
+  Width : Longint;
+  Height : Longint
+):  TCanvasError; external 'web_canvas' name 'fillrect';
+
+function __webcanvas_strokerect(
+  aID : TCanvasID;
+  X : Longint;
+  Y : Longint;
+  Width : Longint;
+  Height : Longint
+):  TCanvasError; external 'web_canvas' name 'strokerect';
+
+
+function __webcanvas_clearrect(
+  aID : TCanvasID;
+  X : Longint;
+  Y : Longint;
+  Width : Longint;
+  Height : Longint
+):  TCanvasError; external 'web_canvas' name 'clearrect';
+
+function __webcanvas_stroketext(
+  aID : TCanvasID;
+  X : Longint;
+  Y : Longint;
+  aText : PByte;
+  aTextLen : Longint
+):  TCanvasError; external 'web_canvas' name 'stroketext';
+
+function __webcanvas_filltext(
+  aID : TCanvasID;
+  X : Longint;
+  Y : Longint;
+  aText : PByte;
+  aTextLen : Longint
+):  TCanvasError; external 'web_canvas' name 'filltext';
+
+
+implementation
+
+end.

File diff suppressed because it is too large
+ 0 - 0
demo/wasienv/simple/bulma.min.css


+ 88 - 0
demo/wasienv/simple/demowasienv.lpi

@@ -0,0 +1,88 @@
+<?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="demowasienv"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <CustomData Count="2">
+      <Item0 Name="MaintainHTML" Value="1"/>
+      <Item1 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="demowasienv.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+      <Unit>
+        <Filename Value="index.html"/>
+        <IsPartOfProject Value="True"/>
+        <CustomData Count="1">
+          <Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
+        </CustomData>
+      </Unit>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target FileExt=".js">
+      <Filename Value="demowasienv"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <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"/>
+      <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>

+ 118 - 0
demo/wasienv/simple/demowasienv.lpr

@@ -0,0 +1,118 @@
+program demowasienv;
+
+{$mode objfpc}
+
+uses
+  browserconsole, browserapp, JS, Classes, SysUtils, Web, WebAssembly, types, wasienv;
+
+Type
+
+  { TMyApplication }
+
+  TMyApplication = class(TBrowserApplication)
+  Private
+    FWasiEnv: TPas2JSWASIEnvironment;
+    FMemory : TJSWebAssemblyMemory; // Memory of webassembly
+    FTable : TJSWebAssemblyTable; // exported functions.
+    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;
+
+begin
+  Result:=True;
+  Exps := TWASIExports(TJSObject(Module.Instance.exports_));
+  FWasiEnv.Instance:=Module.Instance;
+  console.info('got exports', exps);
+  Exps.Start;
+end;
+
+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;
+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('helloworld.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.

+ 6 - 0
demo/wasienv/simple/helloworld.pp

@@ -0,0 +1,6 @@
+program HelloWorld;
+
+begin
+  Writeln('Hello world from FPC webassembly and Pas2JS!');
+  Writeln('... and a merry Christmas for all!');
+end.

+ 47 - 0
demo/wasienv/simple/index.html

@@ -0,0 +1,47 @@
+<!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 and Pas2JS Demo</title>
+  <link href="bulma.min.css" rel="stylesheet">
+  <script src="demowasienv.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">
+    <h1 class="title is-4">FPC compiled wasm program console output:</h1>
+    <div id="pasjsconsole"></div>
+  </div>
+  <hr>
+  <div class="section">
+    <div class="source">
+      <div class="source-inner">
+        <div>
+          <p>Created using &nbsp; <a target="_blank" href="https://wiki.freepascal.org/pas2js">pas2js.</a> </p>
+          <p>Pas2JS Sources: &nbsp; <a target="new" href="demowasienv.lpr">Pas2JS Program</a></p>
+          <p>Webassembly Sources: &nbsp; <a target="new" href="helloworld.pp">FPC Program</a></p>
+        </div>
+      </div>
+    </div>
+  </div>
+  <script>
+    rtl.showUncaughtExceptions=true;
+    rtl.run();
+  </script>
+</body>
+</html>

File diff suppressed because it is too large
+ 0 - 0
demo/wasienv/terminal/bulma.min.css


+ 88 - 0
demo/wasienv/terminal/demowasiterm.lpi

@@ -0,0 +1,88 @@
+<?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="demowasiterm"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <CustomData Count="2">
+      <Item0 Name="MaintainHTML" Value="1"/>
+      <Item1 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="demowasiterm.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+      <Unit>
+        <Filename Value="index.html"/>
+        <IsPartOfProject Value="True"/>
+        <CustomData Count="1">
+          <Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
+        </CustomData>
+      </Unit>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target FileExt=".js">
+      <Filename Value="demowasiterm"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <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"/>
+      <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>

+ 208 - 0
demo/wasienv/terminal/demowasiterm.lpr

@@ -0,0 +1,208 @@
+program demowasiterm;
+
+{$mode objfpc}
+
+uses
+  browserapp, JS, Classes, SysUtils, Web, WebAssembly, types,
+  xterm, wasienv, strutils;
+
+Type
+
+  { TMyApplication }
+
+  TMyApplication = class(TBrowserApplication)
+  Private
+    FTerminal : TXTerm.TTerminal;
+    FTermEl : TJSHTMLElement;
+    FWasiEnv : TPas2JSWASIEnvironment;
+    FMemory : TJSWebAssemblyMemory; // Memory of webassembly
+    FTable:TJSWebAssemblyTable; // Exported functions, directly callable
+    FInputLine : String;
+    Fidx : Integer;
+    FinputLines : TStrings;
+    function CreateWebAssembly(Path: string; ImportObject: TJSObject
+      ): TJSPromise;
+    procedure DoGetInputString(Sender: TObject; var AInput: string);
+    function DoKey(keyData: TXTerm.TOnKeyCallbackDataType): Boolean;
+    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;
+
+begin
+  Result:=True;
+  Exps := TWASIExports(TJSObject(Module.Instance.exports_));
+  FWasiEnv.Instance:=Module.Instance;
+  Exps.Start;
+end;
+
+function TMyApplication.DoKey(keyData : TXTerm.TOnKeyCallbackDataType): Boolean;
+{
+  Experimental code to convert keystrokes to input.
+  Unfortunately, it does not work because the webassembly is executed in the same thread as the javascript.
+  Maybe using a web-worker this can be realized.
+}
+Var
+  printable : Boolean;
+
+begin
+  Result:=true;
+  With keyData do
+    printable :=Not (domEvent.altKey or domEvent.metaKey or domEvent.ctrlKey or domEvent.metaKey);
+  if keyData.domEvent.Key=TJSKeyNames.BackSpace then
+    begin
+    if (Length(FInputLine)>0) then
+      begin
+      FInputLine:=Copy(FInputLine,1,Length(FInputLine)-1);
+      FTerminal.write(#8' '#8);
+      end;
+    end
+  else if (keyData.domEvent.Key=TJSKeyNames.Enter) then
+    begin
+    FInputLine:=FInputLine+#10;
+    FTerminal.writeln('');
+    end
+  else if Printable then
+    begin
+    FInputLine:=FInputLine+keyData.Key;
+    FTerminal.write(keyData.Key);
+    end;
+end;
+
+
+procedure TMyApplication.DoWrite(Sender: TObject; const aOutput: String);
+
+Var
+  S : TStringDynArray;
+  L : String;
+  I,aLen : Integer;
+
+begin
+  S:=SplitString(aOutput,#10);
+  aLen:=length(S)-1;
+  For I:=0 to aLen do
+    begin
+    L:=S[i];
+    FTerminal.Write(L);
+    if I<aLen then
+      FTerminal.Writeln('')
+    end;
+end;
+
+constructor TMyApplication.Create(aOwner: TComponent);
+Var
+  i : Integer;
+begin
+  inherited Create(aOwner);
+  FWasiEnv:=TPas2JSWASIEnvironment.Create;
+  FWasiEnv.OnStdErrorWrite:=@DoWrite;
+  FWasiEnv.OnStdOutputWrite:=@DoWrite;
+  FWasiEnv.OnGetConsoleInputString:=@DoGetInputString;
+  FTermEl:=GetHTMLElement('xterm');
+  FTerminal:=TXTerm.TTerminal.New;
+  FTerminal.OnKey(@DoKey);
+  FTerminal.open(FTermEl);
+  FinputLine:='';
+  FinputLines:=TStringList.Create;
+  Fidx:=0;
+  For I:=0 to 9 do
+    FinputLines.Add(IntToStr(Random(200)));
+  FinputLines.Add('-1');
+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.DoGetInputString(Sender: TObject; var AInput: string);
+
+Var
+  S : String;
+
+begin
+  {
+  // Experimental code for use with keyhandler.
+  aInput:=FInputLine;
+  FInputLine:='';
+  }
+  aInput:='';
+  If FIdx<FInputLines.Count then
+    begin
+    S:=FInputLines[FIdx];
+    aInput:=S+#10;
+    FTerminal.writeln(#27'[31m'+S+#27'[37m');
+    inc(FIdx);
+    end;
+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('sums.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.

+ 50 - 0
demo/wasienv/terminal/index.html

@@ -0,0 +1,50 @@
+<!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 with Pas2JS Terminal Demo</title>
+  <link href="https://unpkg.com/[email protected]/css/xterm.css" rel="stylesheet">
+  <script src="https://unpkg.com/[email protected]/lib/xterm.js"></script>
+  <link href="bulma.min.css" rel="stylesheet">
+  <script src="demowasiterm.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">
+    <h1 class="title is-3">FPC-Webassembly with Pas2JS Terminal Demo</h1>
+    <div class="block">Red color indicates (simulated) terminal input to WebAssembly program</div>
+    <div id="xterm" style="width: 100%; height: 60vh; background-color: black;"></div>
+  </div>
+  <hr>
+  <div class="section">
+    <div class="source">
+      <div class="source-inner">
+        <div>
+          <p>Created using &nbsp; <a target="_blank" href="https://wiki.freepascal.org/pas2js">pas2js.</a> </p>
+          <p>Pas2JS Sources: &nbsp; <a target="new" href="demowasiterm.lpr">Pas2JS Program</a></p>
+          <p>Webassembly Sources: &nbsp; <a target="new" href="sums.pp">FPC Program</a></p>
+        </div>
+      </div>
+    </div>
+  </div>
+  <script>
+    rtl.showUncaughtExceptions=true;
+    window.addEventListener("load", rtl.run);
+  </script>
+</body>
+</html>

+ 19 - 0
demo/wasienv/terminal/sums.pp

@@ -0,0 +1,19 @@
+program HelloWorld;
+
+Var
+  A,B,C : Integer;
+
+begin
+  Writeln('Answer -1 to end the program');
+  Repeat
+    A:=Random(100);
+    B:=Random(100);
+    Write(A,' + ',B,' = ');
+    Readln(C);
+    if (C=(A+B)) then
+      Writeln('Well done !')
+    else if (C<>-1) then
+      Writeln('Sorry, wrong. The correct answer is ',A+B);
+  Until (C=-1);
+end.
+

+ 27 - 0
demo/wasienv/wasienvdemos.lpg

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="canvas/canvasdraw.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="canvas/demowasicanvas.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="simple/demowasienv.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="terminal/demowasiterm.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+    </Targets>
+  </ProjectGroup>
+</CONFIG>

+ 10 - 9
demo/webgl/webgl_demos.lpg

@@ -1,14 +1,15 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <CONFIG>
-  <ProjectGroup FileVersion="1">
-    <Targets Count="4">
-      <Target0 FileName="Pas2JS_WebGL.lpi"/>
-      <Target1 FileName="Pas2JS_WebGL_Minimal.lpi"/>
-      <Target2 FileName="Pas2JS_WebGL_OBJ.lpi">
-        <BuildModes Count="1"/>
-        <Mode1 Name="Default"/>
-      </Target2>
-      <Target3 FileName="Pas2JS_WebGL_Terrain.lpi"/>
+  <ProjectGroup FileVersion="2">
+    <Targets>
+      <Target FileName="Pas2JS_WebGL.lpi"/>
+      <Target FileName="Pas2JS_WebGL_Minimal.lpi"/>
+      <Target FileName="Pas2JS_WebGL_OBJ.lpi">
+        <BuildModes>
+          <Mode Name="Default"/>
+        </BuildModes>
+      </Target>
+      <Target FileName="Pas2JS_WebGL_Terrain.lpi"/>
     </Targets>
   </ProjectGroup>
 </CONFIG>

+ 1150 - 0
packages/wasi/wasienv.pas

@@ -0,0 +1,1150 @@
+
+unit wasienv;
+
+{$mode ObjFPC}
+{$modeswitch externalclass}
+{$INTERFACES CORBA}
+
+interface
+
+uses
+  SysUtils, Classes, JS, WebAssembly, types;
+
+
+Const
+  WASI_ESUCCESS = 0;
+  WASI_E2BIG = 1;
+  WASI_EACCES = 2;
+  WASI_EADDRINUSE = 3;
+  WASI_EADDRNOTAVAIL = 4;
+  WASI_EAFNOSUPPORT = 5;
+  WASI_EAGAIN = 6;
+  WASI_EALREADY = 7;
+  WASI_EBADF = 8;
+  WASI_EBADMSG = 9;
+  WASI_EBUSY = 10;
+  WASI_ECANCELED = 11;
+  WASI_ECHILD = 12;
+  WASI_ECONNABORTED = 13;
+  WASI_ECONNREFUSED = 14;
+  WASI_ECONNRESET = 15;
+  WASI_EDEADLK = 16;
+  WASI_EDESTADDRREQ = 17;
+  WASI_EDOM = 18;
+  WASI_EDQUOT = 19;
+  WASI_EEXIST = 20;
+  WASI_EFAULT = 21;
+  WASI_EFBIG = 22;
+  WASI_EHOSTUNREACH = 23;
+  WASI_EIDRM = 24;
+  WASI_EILSEQ = 25;
+  WASI_EINPROGRESS = 26;
+  WASI_EINTR = 27;
+  WASI_EINVAL = 28;
+  WASI_EIO = 29;
+  WASI_EISCONN = 30;
+  WASI_EISDIR = 31;
+  WASI_ELOOP = 32;
+  WASI_EMFILE = 33;
+  WASI_EMLINK = 34;
+  WASI_EMSGSIZE = 35;
+  WASI_EMULTIHOP = 36;
+  WASI_ENAMETOOLONG = 37;
+  WASI_ENETDOWN = 38;
+  WASI_ENETRESET = 39;
+  WASI_ENETUNREACH = 40;
+  WASI_ENFILE = 41;
+  WASI_ENOBUFS = 42;
+  WASI_ENODEV = 43;
+  WASI_ENOENT = 44;
+  WASI_ENOEXEC = 45;
+  WASI_ENOLCK = 46;
+  WASI_ENOLINK = 47;
+  WASI_ENOMEM = 48;
+  WASI_ENOMSG = 49;
+  WASI_ENOPROTOOPT = 50;
+  WASI_ENOSPC = 51;
+  WASI_ENOSYS = 52;
+  WASI_ENOTCONN = 53;
+  WASI_ENOTDIR = 54;
+  WASI_ENOTEMPTY = 55;
+  WASI_ENOTRECOVERABLE = 56;
+  WASI_ENOTSOCK = 57;
+  WASI_ENOTSUP = 58;
+  WASI_ENOTTY = 59;
+  WASI_ENXIO = 60;
+  WASI_EOVERFLOW = 61;
+  WASI_EOWNERDEAD = 62;
+  WASI_EPERM = 63;
+  WASI_EPIPE = 64;
+  WASI_EPROTO = 65;
+  WASI_EPROTONOSUPPORT = 66;
+  WASI_EPROTOTYPE = 67;
+  WASI_ERANGE = 68;
+  WASI_EROFS = 69;
+  WASI_ESPIPE = 70;
+  WASI_ESRCH = 71;
+  WASI_ESTALE = 72;
+  WASI_ETIMEDOUT = 73;
+  WASI_ETXTBSY = 74;
+  WASI_EXDEV = 75;
+  WASI_ENOTCAPABLE = 76;
+
+  WASI_SIGABRT = 0;
+  WASI_SIGALRM = 1;
+  WASI_SIGBUS = 2;
+  WASI_SIGCHLD = 3;
+  WASI_SIGCONT = 4;
+  WASI_SIGFPE = 5;
+  WASI_SIGHUP = 6;
+  WASI_SIGILL = 7;
+  WASI_SIGINT = 8;
+  WASI_SIGKILL = 9;
+  WASI_SIGPIPE = 10;
+  WASI_SIGQUIT = 11;
+  WASI_SIGSEGV = 12;
+  WASI_SIGSTOP = 13;
+  WASI_SIGTERM = 14;
+  WASI_SIGTRAP = 15;
+  WASI_SIGTSTP = 16;
+  WASI_SIGTTIN = 17;
+  WASI_SIGTTOU = 18;
+  WASI_SIGURG = 19;
+  WASI_SIGUSR1 = 20;
+  WASI_SIGUSR2 = 21;
+  WASI_SIGVTALRM = 22;
+  WASI_SIGXCPU = 23;
+  WASI_SIGXFSZ = 24;
+
+  WASI_FILETYPE_UNKNOWN = 0;
+  WASI_FILETYPE_BLOCK_DEVICE = 1;
+  WASI_FILETYPE_CHARACTER_DEVICE = 2;
+  WASI_FILETYPE_DIRECTORY = 3;
+  WASI_FILETYPE_REGULAR_FILE = 4;
+  WASI_FILETYPE_SOCKET_DGRAM = 5;
+  WASI_FILETYPE_SOCKET_STREAM = 6;
+  WASI_FILETYPE_SYMBOLIC_LINK = 7;
+
+  WASI_FDFLAG_APPEND = $0001;
+  WASI_FDFLAG_DSYNC = $0002;
+  WASI_FDFLAG_NONBLOCK = $0004;
+  WASI_FDFLAG_RSYNC = $0008;
+  WASI_FDFLAG_SYNC = $0010;
+
+  WASI_RIGHT_FD_DATASYNC             = $0000000000000001;
+  WASI_RIGHT_FD_READ                 = $0000000000000002;
+  WASI_RIGHT_FD_SEEK                 = $0000000000000004;
+  WASI_RIGHT_FD_FDSTAT_SET_FLAGS     = $0000000000000008;
+  WASI_RIGHT_FD_SYNC                 = $0000000000000010;
+  WASI_RIGHT_FD_TELL                 = $0000000000000020;
+  WASI_RIGHT_FD_WRITE                = $0000000000000040;
+  WASI_RIGHT_FD_ADVISE               = $0000000000000080;
+  WASI_RIGHT_FD_ALLOCATE             = $0000000000000100;
+  WASI_RIGHT_PATH_CREATE_DIRECTORY   = $0000000000000200;
+  WASI_RIGHT_PATH_CREATE_FILE        = $0000000000000400;
+  WASI_RIGHT_PATH_LINK_SOURCE        = $0000000000000800;
+  WASI_RIGHT_PATH_LINK_TARGET        = $0000000000001000;
+  WASI_RIGHT_PATH_OPEN               = $0000000000002000;
+  WASI_RIGHT_FD_READDIR              = $0000000000004000;
+  WASI_RIGHT_PATH_READLINK           = $0000000000008000;
+  WASI_RIGHT_PATH_RENAME_SOURCE      = $0000000000010000;
+  WASI_RIGHT_PATH_RENAME_TARGET      = $0000000000020000;
+  WASI_RIGHT_PATH_FILESTAT_GET       = $0000000000040000;
+  WASI_RIGHT_PATH_FILESTAT_SET_SIZE  = $0000000000080000;
+  WASI_RIGHT_PATH_FILESTAT_SET_TIMES = $0000000000100000;
+  WASI_RIGHT_FD_FILESTAT_GET         = $0000000000200000;
+  WASI_RIGHT_FD_FILESTAT_SET_SIZE    = $0000000000400000;
+  WASI_RIGHT_FD_FILESTAT_SET_TIMES   = $0000000000800000;
+  WASI_RIGHT_PATH_SYMLINK            = $0000000001000000;
+  WASI_RIGHT_PATH_REMOVE_DIRECTORY   = $0000000002000000;
+  WASI_RIGHT_PATH_UNLINK_FILE        = $0000000004000000;
+  WASI_RIGHT_POLL_FD_READWRITE       = $0000000008000000;
+  WASI_RIGHT_SOCK_SHUTDOWN           = $0000000010000000;
+
+  RIGHTS_ALL = WASI_RIGHT_FD_DATASYNC or WASI_RIGHT_FD_READ
+  or WASI_RIGHT_FD_SEEK or WASI_RIGHT_FD_FDSTAT_SET_FLAGS or WASI_RIGHT_FD_SYNC
+  or WASI_RIGHT_FD_TELL or WASI_RIGHT_FD_WRITE or WASI_RIGHT_FD_ADVISE
+  or WASI_RIGHT_FD_ALLOCATE or WASI_RIGHT_PATH_CREATE_DIRECTORY
+  or WASI_RIGHT_PATH_CREATE_FILE or WASI_RIGHT_PATH_LINK_SOURCE
+  or WASI_RIGHT_PATH_LINK_TARGET or WASI_RIGHT_PATH_OPEN or WASI_RIGHT_FD_READDIR
+  or WASI_RIGHT_PATH_READLINK or WASI_RIGHT_PATH_RENAME_SOURCE
+  or WASI_RIGHT_PATH_RENAME_TARGET or WASI_RIGHT_PATH_FILESTAT_GET
+  or WASI_RIGHT_PATH_FILESTAT_SET_SIZE or WASI_RIGHT_PATH_FILESTAT_SET_TIMES
+  or WASI_RIGHT_FD_FILESTAT_GET or WASI_RIGHT_FD_FILESTAT_SET_TIMES
+  or WASI_RIGHT_FD_FILESTAT_SET_SIZE or WASI_RIGHT_PATH_SYMLINK
+  or WASI_RIGHT_PATH_UNLINK_FILE or WASI_RIGHT_PATH_REMOVE_DIRECTORY
+  or WASI_RIGHT_POLL_FD_READWRITE or WASI_RIGHT_SOCK_SHUTDOWN;
+
+  RIGHTS_BLOCK_DEVICE_BASE = RIGHTS_ALL;
+  RIGHTS_BLOCK_DEVICE_INHERITING = RIGHTS_ALL;
+
+  RIGHTS_CHARACTER_DEVICE_BASE = RIGHTS_ALL;
+  RIGHTS_CHARACTER_DEVICE_INHERITING = RIGHTS_ALL;
+
+  RIGHTS_REGULAR_FILE_BASE = WASI_RIGHT_FD_DATASYNC or WASI_RIGHT_FD_READ
+                           or WASI_RIGHT_FD_SEEK or WASI_RIGHT_FD_FDSTAT_SET_FLAGS or WASI_RIGHT_FD_SYNC
+                           or WASI_RIGHT_FD_TELL or WASI_RIGHT_FD_WRITE or WASI_RIGHT_FD_ADVISE
+                           or WASI_RIGHT_FD_ALLOCATE or WASI_RIGHT_FD_FILESTAT_GET
+                           or WASI_RIGHT_FD_FILESTAT_SET_SIZE or WASI_RIGHT_FD_FILESTAT_SET_TIMES
+                           or WASI_RIGHT_POLL_FD_READWRITE;
+  RIGHTS_REGULAR_FILE_INHERITING = 00;
+
+  RIGHTS_DIRECTORY_BASE = WASI_RIGHT_FD_FDSTAT_SET_FLAGS
+                        or WASI_RIGHT_FD_SYNC or WASI_RIGHT_FD_ADVISE or WASI_RIGHT_PATH_CREATE_DIRECTORY
+                        or WASI_RIGHT_PATH_CREATE_FILE or WASI_RIGHT_PATH_LINK_SOURCE
+                        or WASI_RIGHT_PATH_LINK_TARGET or WASI_RIGHT_PATH_OPEN or WASI_RIGHT_FD_READDIR
+                        or WASI_RIGHT_PATH_READLINK or WASI_RIGHT_PATH_RENAME_SOURCE
+                        or WASI_RIGHT_PATH_RENAME_TARGET or WASI_RIGHT_PATH_FILESTAT_GET
+                        or WASI_RIGHT_PATH_FILESTAT_SET_SIZE or WASI_RIGHT_PATH_FILESTAT_SET_TIMES
+                        or WASI_RIGHT_FD_FILESTAT_GET or WASI_RIGHT_FD_FILESTAT_SET_TIMES
+                        or WASI_RIGHT_PATH_SYMLINK or WASI_RIGHT_PATH_UNLINK_FILE
+                        or WASI_RIGHT_PATH_REMOVE_DIRECTORY or WASI_RIGHT_POLL_FD_READWRITE;
+  RIGHTS_DIRECTORY_INHERITING = RIGHTS_DIRECTORY_BASE
+                        or RIGHTS_REGULAR_FILE_BASE;
+
+  RIGHTS_SOCKET_BASE = WASI_RIGHT_FD_READ or WASI_RIGHT_FD_FDSTAT_SET_FLAGS
+                     or WASI_RIGHT_FD_WRITE or WASI_RIGHT_FD_FILESTAT_GET
+                     or WASI_RIGHT_POLL_FD_READWRITE or WASI_RIGHT_SOCK_SHUTDOWN;
+
+  RIGHTS_SOCKET_INHERITING = RIGHTS_ALL;
+
+  RIGHTS_TTY_BASE = WASI_RIGHT_FD_READ or WASI_RIGHT_FD_FDSTAT_SET_FLAGS
+                  or WASI_RIGHT_FD_WRITE or WASI_RIGHT_FD_FILESTAT_GET
+                  or WASI_RIGHT_POLL_FD_READWRITE;
+
+  RIGHTS_TTY_INHERITING = 0;
+
+  WASI_CLOCK_MONOTONIC = 0;
+  WASI_CLOCK_PROCESS_CPUTIME_ID = 1;
+  WASI_CLOCK_REALTIME = 2;
+  WASI_CLOCK_THREAD_CPUTIME_ID = 3;
+
+  WASI_EVENTTYPE_CLOCK = 0;
+  WASI_EVENTTYPE_FD_READ = 1;
+  WASI_EVENTTYPE_FD_WRITE = 2;
+
+  WASI_FILESTAT_SET_ATIM = 1 << 0;
+  WASI_FILESTAT_SET_ATIM_NOW = 1 << 1;
+  WASI_FILESTAT_SET_MTIM = 1 << 2;
+  WASI_FILESTAT_SET_MTIM_NOW = 1 << 3;
+
+  WASI_O_CREAT = 1 << 0;
+  WASI_O_DIRECTORY = 1 << 1;
+  WASI_O_EXCL = 1 << 2;
+  WASI_O_TRUNC = 1 << 3;
+
+  WASI_PREOPENTYPE_DIR = 0;
+
+  WASI_DIRCOOKIE_START = 0;
+
+  WASI_STDIN_FILENO = 0;
+  WASI_STDOUT_FILENO = 1;
+  WASI_STDERR_FILENO = 2;
+
+  WASI_WHENCE_CUR = 0;
+  WASI_WHENCE_END = 1;
+  WASI_WHENCE_SET = 2;
+
+
+type
+  // The imports as expected by WASI
+  IWASI = interface ['{A03AC61B-3C68-4DA8-AC4F-53ED01814673}']
+    // Please keep these sorted !!
+    function args_get(argc, argvBufSize : NativeInt) : NativeInt;
+    function args_sizes_get(argc, argvBufSize : NativeInt) : NativeInt;
+    function clock_res_get(clockId, resolution: NativeInt): NativeInt;
+    function clock_time_get(clockId, precision, time: NativeInt): NativeInt;
+    function environ_get(environ, environBuf : NativeInt) : NativeInt;
+    function environ_sizes_get(environCount, environBufSize : NativeInt) : NativeInt;
+    function fd_advise (fd, offset, len, advice : NativeInt) : NativeInt;
+    function fd_allocate (fd, offset, len : NativeInt) : NativeInt;
+    function fd_close(fd : NativeInt) : NativeInt;
+    function fd_datasync (fd : NativeInt) : NativeInt;
+    function fd_fdstat_get(fd,bufPtr : NativeInt) : NativeInt;
+    function fd_fdstat_set_flags (fd, flags: NativeInt) : NativeInt;
+    function fd_fdstat_set_rights (fd, fsRightsBase, fsRightsInheriting: NativeInt) : NativeInt;
+    function fd_filestat_get(fd, bufPtr : NativeInt) : NativeInt;
+    function fd_filestat_set_size (fd, stSize: NativeInt) : NativeInt;
+    function fd_filestat_set_times (fd, stAtim, stMtim, fstflags: NativeInt) : NativeInt;
+    function fd_pread(fd, iovs, iovsLen, offset, nread : NativeInt) : NativeInt;
+    function fd_prestat_dir_name(fd, pathPtr, pathLen : NativeInt) : NativeInt;
+    function fd_prestat_get(fd, bufPtr: NativeInt) : NativeInt;
+    function fd_pwrite(fd, iovs, iovsLen, offset, nwritten : NativeInt) : NativeInt;
+    function fd_read(fd, iovs, iovsLen, nread : NativeInt) : NativeInt;
+    function fd_readdir(fd, bufPtr, bufLen, cookie, bufusedPtr : NativeInt) : NativeInt;
+    function fd_renumber(afrom,ato : NativeInt) : NativeInt;
+    function fd_seek(fd, offset, whence, newOffsetPtr : NativeInt) : NativeInt;
+    function fd_sync(fd : NativeInt) : NativeInt;
+    function fd_tell(fd, offsetPtr: NativeInt) : NativeInt;
+    function fd_write(fd,iovs,iovsLen,nwritten : NativeInt) : NativeInt;
+    function path_create_directory (fd, pathPtr, pathLen : NativeInt) : NativeInt;
+    function path_filestat_get (fd, flags, pathPtr, pathLen, bufPtr : NativeInt) : NativeInt;
+    function path_filestat_set_times(fd, fstflags, pathPtr, pathLen, stAtim, stMtim : NativeInt) : NativeInt;
+    function path_link (oldFd, oldFlags, oldPath, oldPathLen, newFd, newPath, newPathLen: NativeInt) : NativeInt;
+    function path_open (dirfd, dirflags, pathPtr, pathLen, oflags, fsRightsBase, fsRightsInheriting, fsFlags, fd : NativeInt) : NativeInt;
+    function path_readlink (fd, pathPtr, pathLen, buf, bufLen, bufused : NativeInt) : NativeInt;
+    function path_remove_directory (fd, pathPtr, pathLen : NativeInt) : NativeInt;
+    function path_rename (oldFd, oldPath, oldPathLen, newFd, newPath, newPathLen : NativeInt) : NativeInt;
+    function path_symlink (oldPath, oldPathLen, fd, newPath, newPathLen : NativeInt) : NativeInt;
+    function path_unlink_file (fd, pathPtr, pathLen : NativeInt) : NativeInt;
+    function poll_oneoff(sin, sout, nsubscriptions, nevents : NativeInt) : NativeInt;
+    function proc_exit(rval : NativeInt) : NativeInt;
+    function proc_raise (sig : NativeInt) : NativeInt;
+    function random_get (bufPtr, bufLen: NativeInt) : NativeInt;
+    function sched_yield() : NativeInt;
+    function sock_recv() : NativeInt;
+    function sock_send() : NativeInt;
+    function sock_shutdown() : NativeInt;
+  end;
+
+  TWASIWriteEvent = Reference to Procedure(Sender : TObject; Const aOutput : String);
+
+  TWASIExports = Class External name 'Object' (TJSObject)
+  Public
+     Procedure start; external name '_start';
+  end;
+
+  TGetConsoleInputBufferEvent = Reference to Procedure(Sender : TObject; Var AInput : TJSUint8Array);
+  TGetConsoleInputStringEvent =Reference to Procedure (Sender : TObject; Var AInput : string);
+
+  TImportExtension = Class;
+
+  { TPas2JSWASIEnvironment }
+
+  TPas2JSWASIEnvironment = class (TObject,IWASI)
+  Private
+    FExitCode: Nativeint;
+    FImportObject : TJSObject;
+    Finstance: TJSWebAssemblyInstance;
+    FIsLittleEndian: Boolean;
+    FModuleInstanceExports : TJSModulesExports;
+    FOnGetConsoleInputBuffer: TGetConsoleInputBufferEvent;
+    FOnGetConsoleInputString: TGetConsoleInputStringEvent;
+    FOnStdErrorWrite: TWASIWriteEvent;
+    FOnStdOutputWrite: TWASIWriteEvent;
+    FImportExtensions : TFPList;
+    FWASIImportName : string;
+    function GetConsoleInputBuffer: TJSUint8Array;
+    function GetFileBuffer(FD: NativeInt): TJSUint8Array;
+    function GetImportObject: TJSObject;
+    function getiovs(view: TJSDataView; iovs, iovsLen: NativeInt): TJSArray;
+    procedure SetInstance(AValue: TJSWebAssemblyInstance);
+  Protected
+    Class Var UTF8TextDecoder: TJSTextDecoder;
+  Protected
+    class procedure setBigUint64(View: TJSDataView; byteOffset, value: NativeInt; littleEndian: Boolean);
+    procedure DoConsoleWrite(IsStdErr: Boolean; aBytes: TJSArray); virtual;
+    procedure GetImports(aImports: TJSObject); virtual;
+    Function GetTime(aClockID : NativeInt): NativeInt; virtual;
+    function getModuleMemoryDataView : TJSDataView;
+    procedure AddExtension(aExtension : TImportExtension); virtual;
+    procedure RemoveExtension(aExtension : TImportExtension); virtual;
+    // IWASI calls
+    // !! Please keep these sorted !!
+
+
+
+    function args_get(argv, argvBuf : NativeInt) : NativeInt; virtual;
+    function args_sizes_get(argc, argvBufSize : NativeInt) : NativeInt; virtual;
+    function clock_res_get(clockId, resolution: NativeInt): NativeInt; virtual;
+    function clock_time_get(clockId, precision, time: NativeInt): NativeInt; virtual;
+    function environ_get(environ, environBuf : NativeInt) : NativeInt; virtual;
+    function environ_sizes_get(environCount, environBufSize : NativeInt) : NativeInt; virtual;
+    function fd_advise (fd, offset, len, advice : NativeInt) : NativeInt; virtual;
+    function fd_allocate (fd, offset, len : NativeInt) : NativeInt; virtual;
+    function fd_close(fd : NativeInt) : NativeInt; virtual;
+    function fd_datasync (fd : NativeInt) : NativeInt; virtual;
+
+    function fd_fdstat_get(fd,bufPtr : NativeInt) : NativeInt; virtual;
+    function fd_fdstat_set_flags (fd, flags: NativeInt) : NativeInt; virtual;
+    function fd_fdstat_set_rights (fd, fsRightsBase, fsRightsInheriting: NativeInt) : NativeInt; virtual;
+    function fd_filestat_get (fd, bufPtr: NativeInt) : NativeInt; virtual;
+    function fd_filestat_set_size (fd, stSize: NativeInt) : NativeInt; virtual;
+    function fd_filestat_set_times (fd, stAtim, stMtim, fstflags: NativeInt) : NativeInt; virtual;
+    function fd_pread(fd, iovs, iovsLen, offset, nread : NativeInt) : NativeInt; virtual;
+    function fd_prestat_dir_name(fd, pathPtr, pathLen : NativeInt) : NativeInt; virtual;
+    function fd_prestat_get(fd, bufPtr: NativeInt) : NativeInt; virtual;
+    function fd_pwrite(fd, iovs, iovsLen, offset, nwritten : NativeInt) : NativeInt;virtual;
+    function fd_read(fd, iovs, iovsLen, nread : NativeInt) : NativeInt; virtual;
+    function fd_readdir(fd, bufPtr, bufLen, cookie, bufusedPtr : NativeInt) : NativeInt; virtual;
+    function fd_renumber(afrom,ato : NativeInt) : NativeInt; virtual;
+    function fd_seek(fd, offset, whence, newOffsetPtr : NativeInt) : NativeInt; virtual;
+    function fd_sync(fd : NativeInt) : NativeInt; virtual;
+    function fd_tell(fd, offsetPtr: NativeInt) : NativeInt; virtual;
+    function fd_write(fd,iovs,iovsLen,nwritten : NativeInt) : NativeInt; virtual;
+    function path_create_directory (fd, pathPtr, pathLen : NativeInt) : NativeInt;
+    function path_filestat_get (fd, flags, pathPtr, pathLen, bufPtr : NativeInt) : NativeInt;
+    function path_filestat_set_times(fd, fstflags, pathPtr, pathLen, stAtim, stMtim : NativeInt) : NativeInt;
+    function path_link (oldFd, oldFlags, oldPath, oldPathLen, newFd, newPath, newPathLen: NativeInt) : NativeInt;
+    function path_open (dirfd, dirflags, pathPtr, pathLen, oflags, fsRightsBase, fsRightsInheriting, fsFlags, fd : NativeInt) : NativeInt; virtual;
+    function path_readlink (fd, pathPtr, pathLen, buf, bufLen, bufused : NativeInt) : NativeInt; virtual;
+    function path_remove_directory (fd, pathPtr, pathLen : NativeInt) : NativeInt;
+    function path_rename (oldFd, oldPath, oldPathLen, newFd, newPath, newPathLen : NativeInt) : NativeInt;
+    function path_symlink (oldPath, oldPathLen, fd, newPath, newPathLen : NativeInt) : NativeInt;
+    function path_unlink_file (fd, pathPtr, pathLen : NativeInt) : NativeInt;
+    function poll_oneoff(sin, sout, nsubscriptions, nevents : NativeInt) : NativeInt; virtual;
+    function proc_exit(rval : NativeInt) : NativeInt; virtual;
+    function proc_raise (sig : NativeInt) : NativeInt; virtual;
+    function random_get (bufPtr, bufLen: NativeInt) : NativeInt; virtual;
+    function sched_yield() : NativeInt; virtual;
+    function sock_recv() : NativeInt; virtual;
+    function sock_send() : NativeInt; virtual;
+    function sock_shutdown() : NativeInt; virtual;
+  Public
+    class constructor init;
+    Constructor Create;
+    Destructor Destroy; override;
+    Function GetUTF8StringFromMem(aLoc, aLen : Longint) : String;
+    // Add imports
+    Procedure AddImports(aObject: TJSObject); 
+    Property ImportObject : TJSObject Read GetImportObject;
+    Property IsLittleEndian : Boolean Read FIsLittleEndian Write FIsLittleEndian;
+    Property OnStdOutputWrite : TWASIWriteEvent Read FOnStdOutputWrite Write FOnStdOutputWrite;
+    Property OnStdErrorWrite : TWASIWriteEvent Read FOnStdErrorWrite Write FOnStdErrorWrite;
+    Property OnGetConsoleInputBuffer : TGetConsoleInputBufferEvent Read FOnGetConsoleInputBuffer Write FOnGetConsoleInputBuffer;
+    Property OnGetConsoleInputString : TGetConsoleInputStringEvent Read FOnGetConsoleInputString Write FOnGetConsoleInputString;
+    Property Instance : TJSWebAssemblyInstance Read Finstance Write SetInstance;
+    Property Exitcode : Nativeint Read FExitCode;
+    // Default is set to the one expected by FPC runtime: wasi_snapshot_preview1
+    Property WASIImportName : String Read FWASIImportName Write FWASIImportName;
+  end;
+
+  { TImportExtension }
+
+  TImportExtension = class (TObject)
+  Private
+    FEnv : TPas2JSWASIEnvironment;
+  Protected
+    function getModuleMemoryDataView : TJSDataView;  
+  Public
+    Constructor Create(aEnv : TPas2JSWASIEnvironment); virtual;
+    Destructor Destroy; override;
+    Procedure FillImportObject(aObject : TJSObject); virtual; abstract;
+    Function ImportName : String; virtual; abstract;
+    Property Env : TPas2JSWASIEnvironment Read FEnv;
+  end;
+
+implementation
+
+uses web;
+
+function TImportExtension.getModuleMemoryDataView : TJSDataView;  
+
+begin
+  Result:=FEnv.getModuleMemoryDataView;
+end;
+
+constructor TImportExtension.Create(aEnv: TPas2JSWASIEnvironment);
+
+begin
+  FEnv:=aEnv;
+  if Assigned(Fenv) then
+    Fenv.AddExtension(Self);
+end;
+
+destructor TImportExtension.Destroy;
+begin
+  if Assigned(Fenv) then
+    Fenv.RemoveExtension(Self);
+  inherited Destroy;
+end;
+
+procedure TPas2JSWASIEnvironment.AddImports(aObject: TJSObject);
+
+Var
+  Ext : TImportExtension;
+  I : Integer;
+  O : TJSObject;
+  
+begin
+  aObject[WASIImportName]:=ImportObject;
+  For I:=0 to FImportExtensions.Count-1 do
+    begin
+    Ext:=TImportExtension(FImportExtensions[i]);
+    O:=TJSObject.New;
+    Ext.FillImportObject(O);
+    aObject[Ext.ImportName]:=O;
+    end;
+end;
+
+procedure TPas2JSWASIEnvironment.AddExtension(aExtension : TImportExtension); 
+begin
+  if Not Assigned(FImportExtensions) then
+    FImportExtensions:=TFPList.Create;
+  FImportExtensions.Add(aExtension);
+end;
+
+procedure TPas2JSWASIEnvironment.RemoveExtension(aExtension: TImportExtension);
+
+begin
+ if Assigned(FImportExtensions) then
+   FImportExtensions.Remove(aExtension);
+end;
+
+function TPas2JSWASIEnvironment.getModuleMemoryDataView: TJSDataView;
+begin
+  Result:=TJSDataView.New(FModuleInstanceExports.memory.buffer);
+end;
+
+function TPas2JSWASIEnvironment.fd_prestat_get(fd, bufPtr: NativeInt
+  ): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_prestat_get');
+  Result:=WASI_EBADF;
+end;
+
+function TPas2JSWASIEnvironment.fd_prestat_dir_name(fd, pathPtr,
+  pathLen: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_prestat_dir_name');
+  Result:=WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.environ_sizes_get(environCount,
+  environBufSize: NativeInt): NativeInt;
+
+Var
+  View : TJSDataView;
+
+begin
+  view:=getModuleMemoryDataView();
+  view.setUint32(environCount, 0, IsLittleEndian);
+  view.setUint32(environBufSize, 0, IsLittleEndian);
+  Result:= WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.environ_get(environ, environBuf: NativeInt
+  ): NativeInt;
+begin
+  Result:= WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.args_sizes_get(argc, argvBufSize: NativeInt
+  ): NativeInt;
+
+Var
+  View : TJSDataView;
+
+begin
+  view:=getModuleMemoryDataView();
+  view.setUint32(argc, 0, IsLittleEndian);
+  view.setUint32(argvBufSize, 0, IsLittleEndian);
+  Result:=WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.args_get(argv, argvBuf: NativeInt): NativeInt;
+begin
+  Result:=WASI_ESUCCESS;
+end;
+
+class procedure TPas2JSWASIEnvironment.setBigUint64(View: TJSDataView;
+  byteOffset, value: NativeInt; littleEndian: Boolean);
+
+Var
+  LowWord,HighWord : Integer;
+
+begin
+  lowWord:=value;
+  highWord:=0;
+  if LittleEndian then
+    begin
+    view.setUint32(ByteOffset+0, lowWord, littleEndian);
+    view.setUint32(ByteOffset+4, highWord, littleEndian);
+    end
+  else
+    begin
+    view.setUint32(ByteOffset+4, lowWord, littleEndian);
+    view.setUint32(ByteOffset+0, highWord, littleEndian);
+    end;
+end;
+
+procedure TPas2JSWASIEnvironment.SetInstance(AValue: TJSWebAssemblyInstance);
+begin
+  if Finstance=AValue then Exit;
+  Finstance:=AValue;
+  FModuleInstanceExports:=Finstance.exports_;
+end;
+
+function TPas2JSWASIEnvironment.GetTime(aClockID: NativeInt): NativeInt;
+begin
+  Result:=-1;
+  Case aClockId of
+  WASI_CLOCK_MONOTONIC:
+    Result:=TJSDate.Now;
+  WASI_CLOCK_REALTIME:
+    Result:=TJSDate.Now;
+  WASI_CLOCK_PROCESS_CPUTIME_ID,
+  WASI_CLOCK_THREAD_CPUTIME_ID:
+    Result:=TJSDate.Now;
+  end;
+end;
+
+
+function TPas2JSWASIEnvironment.fd_fdstat_get(fd, bufPtr: NativeInt): NativeInt;
+
+Var
+  View : TJSDataView;
+
+begin
+  view:=getModuleMemoryDataView();
+  view.setUint8(bufPtr, fd);
+  view.setUint16(bufPtr + 2, 0, IsLittleEndian);
+  view.setUint16(bufPtr + 4, 0, IsLittleEndian);
+  setBigUint64(View, bufPtr + 8, 0, IsLittleEndian);
+  setBigUint64(View, bufPtr + 8 + 8, 0, IsLittleEndian);
+  Result:= WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.fd_fdstat_set_flags(fd, flags: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_fdstat_set_flags');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_fdstat_set_rights(fd, fsRightsBase, fsRightsInheriting: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_fdstat_set_rights');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.getiovs(view: TJSDataView; iovs,
+  iovsLen: NativeInt): TJSArray;
+
+Var
+  I : integer;
+  ArrayBuf : TJSUint8Array;
+  Ptr,Buf,BufLen : Integer;
+
+begin
+  Result:=TJSArray.New;
+  For I:=0 to iovsLen-1 do
+    begin
+    ptr:=iovs + i * 8;
+    buf:=view.getUint32(ptr, IsLittleEndian);
+    bufLen:=view.getUint32(ptr + 4, IsLittleEndian);
+    ArrayBuf:=TJSUint8Array.New(FModuleInstanceExports.memory.buffer, buf, bufLen);
+    Result.Push(ArrayBuf);
+    end;
+end;
+
+function TPas2JSWASIEnvironment.fd_write(fd, iovs, iovsLen, nwritten: NativeInt): NativeInt;
+
+var
+  view : TJSDataView;
+  written : NativeInt;
+  bufferBytes : TJSArray;
+  Buffers : TJSArray;
+
+  function writev(element : JSValue; index: NativeInt; anArray : TJSArray) : Boolean;
+
+  var
+    b : NativeInt;
+    iov: TJSUint8Array absolute Element;
+
+  begin
+    For b:=0 to iov.byteLength-1 do
+       bufferBytes.push(iov[b]);
+    Inc(Written,iov.byteLength);
+    Result:=true;
+  end;
+
+
+begin
+  BufferBytes:=TJSArray.New;
+  view:=getModuleMemoryDataView();
+  written:=0;
+  buffers:=getiovs(view, iovs, iovsLen);
+  buffers.forEach(@writev);
+  if (fd = WASI_STDOUT_FILENO) or (fd = WASI_STDERR_FILENO) then
+    DoConsoleWrite((fd=WASI_STDERR_FILENO),BufferBytes);
+  view.setUint32(nwritten, written, IsLittleEndian);
+  Result:=WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.fd_pwrite(fd, iovs, iovsLen, offset,
+  nwritten: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_pwrite');
+  Result:=WASI_ENOSYS;
+end;
+
+procedure TPas2JSWASIEnvironment.DoConsoleWrite(IsStdErr: Boolean;
+  aBytes: TJSArray);
+
+Var
+  S : String;
+
+begin
+  asm
+    // Result=String.fromCharCode.apply(null, new Uint16Array(a));
+    S=String.fromCharCode.apply(null, aBytes);
+  end;
+  if IsStdErr then
+    begin
+    if Assigned(FOnStdErrorWrite) then
+      FOnStdErrorWrite(Self,S)
+    end
+  else
+    begin
+    if Assigned(FOnStdOutputWrite) then
+      FOnStdOutputWrite(Self,S)
+    end
+end;
+
+function TPas2JSWASIEnvironment.clock_res_get (clockId, resolution : NativeInt) : NativeInt;
+Var
+  view: TJSDataView;
+
+begin
+  view:=getModuleMemoryDataView;
+  setBigUint64(view,resolution, 0,IsLittleEndian);
+  Result:=WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.clock_time_get(clockId, precision, time: NativeInt) : NativeInt;
+
+Var
+  view: TJSDataView;
+  n : NativeInt;
+begin
+  view:=getModuleMemoryDataView;
+  n:=GetTime(clockId);
+  if N=-1 then
+    Result:=WASI_EINVAL
+  else
+    begin
+    setBigUint64(view,time,n,IsLittleEndian);
+    Result:=WASI_ESUCCESS;
+    end;
+end;
+
+function TPas2JSWASIEnvironment.GetImportObject: TJSObject;
+
+begin
+  // We need this trick to be able to access self or this.
+  // The webassembly callbacks get called without a this.
+  if Not Assigned(FImportObject) then
+    begin
+    FImportObject:=TJSObject.New;
+    GetImports(FImportObject);
+    end;
+  Result:=FImportObject;
+end;
+
+procedure TPas2JSWASIEnvironment.GetImports(aImports: TJSObject);
+
+begin
+  aImports['args_get']:=@args_get;
+  aImports['args_sizes_get']:=@args_sizes_get;
+  aImports['clock_res_get']:=@clock_res_get;
+  aImports['clock_time_get']:=@clock_time_get;
+  aImports['environ_get']:=@environ_get;
+  aImports['environ_sizes_get']:=@environ_sizes_get;
+  aImports['fd_advise']:=@fd_advise;
+  aImports['fd_allocate']:=@fd_allocate;
+  aImports['fd_close']:=@fd_close;
+  aImports['fd_datasync']:=@fd_datasync;
+  aImports['fd_fdstat_get']:=@fd_fdstat_get;
+  aImports['fd_fdstat_set_flags']:=@fd_fdstat_set_flags;
+  aImports['fd_fdstat_set_rights']:=@fd_fdstat_set_rights;
+  aImports['fd_filestat_get']:=@fd_filestat_get;
+  aImports['fd_filestat_set_size']:=@fd_filestat_set_size;
+  aImports['fd_filestat_set_times']:=@fd_filestat_set_times;
+  aImports['fd_pread']:=@fd_pread;
+  aImports['fd_prestat_dir_name']:=@fd_prestat_dir_name;
+  aImports['fd_prestat_get']:=@fd_prestat_get;
+  aImports['fd_pwrite']:=@fd_pwrite;
+  aImports['fd_read']:=@fd_read;
+  aImports['fd_readdir']:=@fd_readdir;
+  aImports['fd_renumber']:=@fd_renumber;
+  aImports['fd_seek']:=@fd_seek;
+  aImports['fd_sync']:=@fd_sync;
+  aImports['fd_tell']:=@fd_tell;
+  aImports['fd_write']:=@fd_write;
+  aImports['path_create_directory']:=@path_create_directory;
+  aImports['path_filestat_get']:=@path_filestat_get;
+  aImports['path_filestat_set_times']:=@path_filestat_set_times;
+  aImports['path_link']:=@path_link;
+  aImports['path_open']:=@path_open;
+  aImports['path_readlink']:=@path_readlink;
+  aImports['path_remove_directory']:=@path_remove_directory;
+  aImports['path_rename']:=@path_rename;
+  aImports['path_symlink']:=@path_symlink;
+  aImports['path_unlink_file']:=@path_unlink_file;
+  aImports['poll_oneoff']:=@poll_oneoff;
+  aImports['proc_exit']:=@proc_exit;
+  aImports['proc_raise']:=@proc_raise;
+  aImports['random_get']:=@random_get;
+  aImports['sched_yield']:=@sched_yield;
+  aImports['sock_recv']:=@sock_recv;
+  aImports['sock_recv']:=@sock_recv;
+  aImports['sock_shutdown']:=@sock_shutdown;
+end;
+
+function TPas2JSWASIEnvironment.poll_oneoff(sin, sout, nsubscriptions,
+  nevents: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.poll_oneoff');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.proc_exit(rval: NativeInt): NativeInt;
+begin
+  FExitCode:=rval;
+  Result:=WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.proc_raise(sig: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.proc_raise');
+  Result:=WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.random_get(bufPtr, bufLen: NativeInt ): NativeInt;
+var
+  arr: TJSUint8Array;
+  I : integer;
+  View : TJSDataView;
+begin
+  arr:=TJSUint8Array.new(BufLen);
+  window.crypto.getRandomValues(arr);
+  view:=getModuleMemoryDataView;
+  For I:=0 to arr.length-1 do
+    view.setInt8(bufptr+i,arr[i]);
+  Result:=WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.sched_yield: NativeInt;
+begin
+  Result:=WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.sock_recv: NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.sock_recv');
+  Result:=WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.sock_send: NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.sock_recv');
+  Result:=WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.sock_shutdown: NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.sock_shutdown');
+  Result:=WASI_ENOSYS;
+end;
+
+class constructor TPas2JSWASIEnvironment.init;
+Var
+  Opts : TJSTextDecoderOptions;
+
+begin
+  Opts:=TJSTextDecoderOptions.New;
+  Opts.ignoreBOM:=true;
+  Opts.fatal:=True;
+  UTF8TextDecoder:=TJSTextDecoder.new ('utf-8',Opts);
+end;
+
+function TPas2JSWASIEnvironment.fd_advise(fd, offset, len, advice: NativeInt
+  ): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_advise');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_allocate(fd, offset, len: NativeInt
+  ): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_allocate');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_close(fd: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_close');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_datasync(fd: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_datasync');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_seek(fd, offset, whence,
+  newOffsetPtr: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_seek');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_sync(fd: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_sync');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_pread(fd, iovs, iovsLen, offset,
+  nread: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_pread');
+  Result:= WASI_ENOSYS;
+end;
+
+
+function toUTF8Array(str : string) : TJSUint8Array;
+
+Var
+  Len,I,P : integer;
+  charCode : NativeInt;
+
+  procedure push (abyte : Byte);
+
+  begin
+    Result[P]:=aByte;
+    inc(P);
+  end;
+
+begin
+  Result:=TJSUint8Array.new(Length(str)*4);
+  P:=0;
+  Len:=Length(str);
+  I:=1;
+  While i<=Len do
+    begin
+    charcode:=Ord(Str[i]);
+    if (charcode < $80) then
+      push(charcode)
+    else if (charcode < $800) then
+      begin
+      push($c0 or (charcode shr 6));
+      push($80 or (charcode and $3f));
+      end
+    else if (charcode < $d800) or (charcode >= $e000) then
+      begin
+      push($e0 or (charcode shr 12));
+      push($80 or ((charcode shr 6) and $3f));
+      push($80 or (charcode and $3f));
+      end
+    else
+      begin
+      Inc(I);
+      // UTF-16 encodes 0x10000-0x10FFFF by
+      // subtracting 0x10000 and splitting the
+      // 20 bits of 0x0-0xFFFFF into two halves
+      charcode := $10000 + (((charcode and $3ff) shl 10) or (Ord(Str[i]) and $3ff));
+      push($f0 or (charcode shr 18));
+      push($80 or ((charcode shr 12) and $3f));
+      push($80 or ((charcode shr 6) and $3f));
+      push($80 or (charcode and $3f));
+      end;
+    inc(I);
+    end;
+  Result:=TJSUint8Array(Result.slice(0,p));
+end;
+
+function TPas2JSWASIEnvironment.fd_read(fd, iovs, iovsLen, nread: NativeInt
+  ): NativeInt;
+var
+  view : TJSDataView;
+  bytesRead : NativeInt;
+  bufferBytes : TJSUint8Array;
+  Buffers : TJSArray;
+
+  function readv(element : JSValue; index: NativeInt; anArray : TJSArray) : Boolean;
+
+  var
+    b : NativeInt;
+    iov: TJSUint8Array absolute Element;
+
+  begin
+    b:=0;
+    While (B<iov.byteLength) and (BytesRead<BufferBytes.Length) do
+      begin
+      iov[b]:=BufferBytes[BytesRead];
+      inc(b);
+      inc(BytesRead);
+      end;
+    Result:=true;
+  end;
+
+
+begin
+  bytesRead:=0;
+  view:=getModuleMemoryDataView();
+  if (fd = WASI_STDIN_FILENO) then
+    begin
+    BufferBytes:=GetConsoleInputBuffer
+    end
+  else
+    BufferBytes:=GetFileBuffer(FD);
+  if BufferBytes.length>0 then
+    begin
+    buffers:=getiovs(view, iovs, iovsLen);
+    buffers.forEach(@readv);
+    end;
+  view.setUint32(nread, bytesRead, IsLittleEndian);
+  Result:=WASI_ESUCCESS;
+end;
+
+function TPas2JSWASIEnvironment.GetFileBuffer(FD : NativeInt): TJSUint8Array;
+
+begin
+  Result:=TJSUint8Array.new(0);
+end;
+
+function TPas2JSWASIEnvironment.GetConsoleInputBuffer : TJSUint8Array;
+
+Var
+  S : String;
+
+begin
+  Result:=Nil;
+  If Assigned(OnGetConsoleInputBuffer) then
+    OnGetConsoleInputBuffer(Self,Result)
+  else If Assigned(OnGetConsoleInputString) then
+    begin
+    S:='';
+    OnGetConsoleInputString(Self,S);
+    Result:=toUTF8Array(S);
+    end
+  else
+    Result:=TJSUint8Array.New(0);
+end;
+
+function TPas2JSWASIEnvironment.fd_readdir(fd, bufPtr, bufLen, cookie,
+  bufusedPtr: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_readdir');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_renumber(afrom, ato: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_renumber');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_tell(fd, offsetPtr: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_tell');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_filestat_get(fd, bufPtr: NativeInt
+  ): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_filestat_get');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_filestat_set_size(fd, stSize: NativeInt
+  ): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_filestat_set_size');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.fd_filestat_set_times(fd, stAtim, stMtim,
+  fstflags: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.fd_filestat_set_times');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_readlink(fd, pathPtr, pathLen, buf,
+  bufLen, bufused: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_readlink');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_create_directory(fd, pathPtr,
+  pathLen: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_create_directory');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_filestat_get(fd, flags, pathPtr, pathLen,
+  bufPtr: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_filestat_get');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_link(oldFd, oldFlags, oldPath, oldPathLen,
+  newFd, newPath, newPathLen: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_link');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_remove_directory(fd, pathPtr,
+  pathLen: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_remove_directory');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_rename(oldFd, oldPath, oldPathLen, newFd,
+  newPath, newPathLen: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_rename');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_symlink(oldPath, oldPathLen, fd, newPath,
+  newPathLen: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_symlink');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_unlink_file(fd, pathPtr, pathLen: NativeInt
+  ): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_unlink_file');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_open(dirfd, dirflags, pathPtr, pathLen,
+  oflags, fsRightsBase, fsRightsInheriting, fsFlags, fd: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_open');
+  Result:= WASI_ENOSYS;
+end;
+
+function TPas2JSWASIEnvironment.path_filestat_set_times(fd, fstflags, pathPtr,
+  pathLen, stAtim, stMtim: NativeInt): NativeInt;
+begin
+  console.log('Unimplemented: TPas2JSWASIEnvironment.path_filestat_set_times');
+  Result:= WASI_ENOSYS;
+end;
+
+constructor TPas2JSWASIEnvironment.Create;
+begin
+  FIsLittleEndian:=True;
+  // Default expected by FPC runtime
+  WASIImportName:='wasi_snapshot_preview1';
+end;
+
+destructor TPas2JSWASIEnvironment.Destroy;
+begin
+  FreeAndNil(FImportExtensions);
+  inherited Destroy;
+end;
+
+
+function TPas2JSWASIEnvironment.GetUTF8StringFromMem(aLoc, aLen: Longint): String;
+begin
+  Result:=UTF8TextDecoder.Decode(getModuleMemoryDataView.buffer.slice(aLoc,aLoc+alen));
+end;
+
+initialization
+
+end.
+

Some files were not shown because too many files changed in this diff