Преглед на файлове

* WASIHostApplication object

Michaël Van Canneyt преди 3 години
родител
ревизия
4469f8defe
променени са 5 файла, в които са добавени 355 реда и са изтрити 0 реда
  1. 0 0
      demo/wasienv/wasiapp/bulma.min.css
  2. 92 0
      demo/wasienv/wasiapp/demowasiapp.lpi
  3. 49 0
      demo/wasienv/wasiapp/demowasiapp.lpr
  4. 49 0
      demo/wasienv/wasiapp/index.html
  5. 165 0
      packages/wasi/wasihostapp.pas

Файловите разлики са ограничени, защото са твърде много
+ 0 - 0
demo/wasienv/wasiapp/bulma.min.css


+ 92 - 0
demo/wasienv/wasiapp/demowasiapp.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="demowasiapp"/>
+      <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="demowasiapp.lpr"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+      <Unit>
+        <Filename Value="../simple/index.html"/>
+        <IsPartOfProject Value="True"/>
+        <CustomData Count="1">
+          <Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
+        </CustomData>
+      </Unit>
+      <Unit>
+        <Filename Value="../../../packages/wasi/wasihostapp.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target FileExt=".js">
+      <Filename Value="demowasiapp"/>
+    </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>

+ 49 - 0
demo/wasienv/wasiapp/demowasiapp.lpr

@@ -0,0 +1,49 @@
+program demowasiapp;
+
+{$mode objfpc}
+
+uses
+  browserconsole, browserapp, JS, Classes, SysUtils, Web, WebAssembly, types,
+  wasienv, wasihostapp;
+
+Type
+
+  { TMyApplication }
+
+  TMyApplication = class(TWASIHostApplication)
+  Private
+    procedure DoWrite(Sender: TObject; const aOutput: String);
+  Public
+    Constructor Create(aOwner : TComponent); override;
+    procedure doRun; override;
+  end;
+
+
+procedure TMyApplication.DoWrite(Sender: TObject; const aOutput: String);
+begin
+  Writeln(aOutput);
+end;
+
+constructor TMyApplication.Create(aOwner: TComponent);
+begin
+  inherited Create(aOwner);
+  WasiEnvironment.OnStdErrorWrite:=@DoWrite;
+  WasiEnvironment.OnStdOutputWrite:=@DoWrite;
+end;
+
+procedure TMyApplication.doRun;
+
+begin
+  // Your code here
+  Terminate;
+  StartWebAssembly('helloworld.wasm');
+end;
+
+var
+  Application : TMyApplication;
+
+begin
+  Application:=TMyApplication.Create(nil);
+  Application.Initialize;
+  Application.Run;
+end.

+ 49 - 0
demo/wasienv/wasiapp/index.html

@@ -0,0 +1,49 @@
+
+<!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">
+  <!-- <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/css/bulma.min.css"> -->
+  <script src="demowasiapp.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 pb-4">
+    <h1 class="title is-4">FPC compiled wasm program console output:</h1>
+    <div class="box" id="pasjsconsole"></div>
+  </div>
+  <!-- <hr> -->
+  <div class="section">
+    <div class="source">
+      <div class="source-inner">
+        <div>
+          <p>Created using &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>

+ 165 - 0
packages/wasi/wasihostapp.pas

@@ -0,0 +1,165 @@
+unit wasihostapp;
+
+{$mode ObjFPC}
+
+interface
+
+uses
+  Classes, SysUtils, JS, browserapp, web, webassembly, wasienv;
+
+Type
+  TStartDescriptor = record
+    Memory : TJSWebAssemblyMemory;
+    Table : TJSWebAssemblyTable;
+    Exported : TWASIExports;
+    Instance : TJSWebAssemblyInstance;
+  end;
+
+  { TWASIHostApplication }
+  TStartCallBack = Reference to Function (Sender : TObject; aDescriptor : TStartDescriptor) : Boolean;
+
+  TWASIHostApplication = class(TBrowserApplication)
+  private
+    FEnv: TPas2JSWASIEnvironment;
+    FExported: TWASIExports;
+    FMemoryDescriptor : TJSWebAssemblyMemoryDescriptor;
+    FRunEntryFunction: String;
+    FTableDescriptor : TJSWebAssemblyTableDescriptor;
+    procedure DoStdRead(Sender: TObject; var AInput: string);
+  protected
+    procedure DoStdWrite(Sender: TObject; const aOutput: String); virtual;
+    function CreateWebAssembly(aPath: string; aImportObject: TJSObject): TJSPromise; virtual;
+    Function CreateWasiEnvironment : TPas2JSWASIEnvironment; virtual;
+    function GetTable: TJSWebAssemblyTable; virtual;
+    function GetMemory: TJSWebAssemblyMemory; virtual;
+ public
+    Constructor Create(aOwner : TComponent); override;
+    Destructor Destroy; override;
+    // Load and start webassembly. If DoRun is true, then Webassembly entry point is called.
+    // If aCallback is specified, then it is called prior to calling run.
+    Procedure StartWebAssembly(aPath: string; DoRun : Boolean = True;  aCallBack : TStartCallback = Nil);
+    // Initial memory descriptor
+    Property MemoryDescriptor : TJSWebAssemblyMemoryDescriptor Read FMemoryDescriptor Write FMemoryDescriptor;
+    // Import/export table descriptor
+    Property TableDescriptor : TJSWebAssemblyTableDescriptor Read FTableDescriptor Write FTableDescriptor;
+    // Environment to be used
+    Property WasiEnvironment : TPas2JSWASIEnvironment Read FEnv;
+    // Exported functions. Also available in start descriptor.
+    Property Exported : TWASIExports Read FExported;
+    Property RunEntryFunction : String Read FRunEntryFunction Write FRunEntryFunction;
+  end;
+
+implementation
+
+{ TWASIHostApplication }
+
+function TWASIHostApplication.CreateWasiEnvironment: TPas2JSWASIEnvironment;
+begin
+  Result:=TPas2JSWASIEnvironment.Create;
+end;
+
+constructor TWASIHostApplication.Create(aOwner: TComponent);
+begin
+  inherited Create(aOwner);
+  FEnv:=CreateWasiEnvironment;
+  FEnv.OnStdErrorWrite:=@DoStdWrite;
+  FEnv.OnStdOutputWrite:=@DoStdWrite;
+  Fenv.OnGetConsoleInputString:=@DoStdRead;
+  FMemoryDescriptor.initial:=256;
+  FMemoryDescriptor.maximum:=256;
+  FTableDescriptor.initial:=0;
+  FTableDescriptor.maximum:=0;
+  FTableDescriptor.element:='anyfunc';
+end;
+
+destructor TWASIHostApplication.Destroy;
+begin
+  FreeAndNil(FEnv);
+  inherited Destroy;
+end;
+
+function TWASIHostApplication.GetTable : TJSWebAssemblyTable;
+
+begin
+  Result:=TJSWebAssemblyTable.New(FTableDescriptor);
+end;
+
+function TWASIHostApplication.GetMemory : TJSWebAssemblyMemory;
+
+begin
+  Result:=TJSWebAssemblyMemory.New(FMemoryDescriptor);
+end;
+
+
+procedure TWASIHostApplication.StartWebAssembly(aPath: string; DoRun : Boolean = True;  ACallBack: TStartCallback = Nil);
+
+Var
+  ImportObj : TJSObject;
+  Res : TStartDescriptor;
+
+  function InitEnv(aValue: JSValue): JSValue;
+
+  Var
+    Module : TJSInstantiateResult absolute aValue;
+
+  begin
+    Result:=True;
+    Res.Instance:=Module.Instance;
+    Res.Exported:=TWASIExports(TJSObject(Module.Instance.exports_));
+    // These 2 prevent running different instances simultaneously.
+    FExported:=Res.Exported;
+    WasiEnvironment.Instance:=Module.Instance;
+    if Assigned(aCallBack) then
+      DoRun:=aCallBack(Self,Res) and DoRun;
+    if DoRun then
+      if FRunEntryFunction='' then
+        Res.Exported.Start
+      else
+        TProcedure(Res.Exported[RunEntryFunction])();
+  end;
+
+
+begin
+  Res.Memory:=GetMemory;
+  Res.Table:=GetTable;
+  ImportObj:=new([
+    'js', new([
+      'mem', Res.Memory,
+      'tbl', Res.Table
+    ])
+  ]);
+  FEnv.AddImports(ImportObj);
+  CreateWebAssembly(aPath,ImportObj)._then(@initEnv)
+end;
+
+procedure TWASIHostApplication.DoStdRead(Sender: TObject; var AInput: string);
+begin
+  aInput:=Window.prompt('Please enter the input for the running webassembly program.');
+end;
+
+procedure TWASIHostApplication.DoStdWrite(Sender: TObject; const aOutput: String
+  );
+begin
+  Console.log('Webassembly output: ', aOutput);
+end;
+
+function TWASIHostApplication.CreateWebAssembly(aPath: string; aImportObject: TJSObject): TJSPromise;
+
+  Function ArrayOK(res2 : jsValue) : JSValue;
+
+  begin
+     Result:=TJSWebAssembly.instantiate(TJSArrayBuffer(res2),aImportObject);
+  end;
+
+  function fetchOK(res : jsValue) : JSValue;
+  begin
+    Result:=TJSResponse(Res).arrayBuffer._then(@ArrayOK,Nil)
+  end;
+
+begin
+  Result:=window.fetch(aPath)._then(@fetchOK,Nil);
+end;
+
+
+end.
+

Някои файлове не бяха показани, защото твърде много файлове са промени