Explorar el Código

* message channel demo

Michael Van Canneyt hace 1 mes
padre
commit
383603c9b1

+ 8 - 0
demo/wasienv/messages/Readme.md

@@ -0,0 +1,8 @@
+# Webassembly Message Channel api demo.
+
+This demo shows how to do broadcast channel messages from Webassembly. 
+
+To make this demo work, you need to compile the channeldemo.lpr example
+project that comes with fpc (in `packages/wasm-utils/demos/messagechannel/channeldemo.lpr`), 
+and put it in this demo directory.
+

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
demo/wasienv/messages/bulma.min.css


+ 3 - 0
demo/wasienv/messages/hostConfig.js

@@ -0,0 +1,3 @@
+var hostConfig = {
+  
+}

+ 41 - 0
demo/wasienv/messages/index.html

@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="UTF-8">
+    <title>Wasm Message channel demo</title>
+    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"> <!-- Prevents caching -->
+    <meta http-equiv="Pragma" content="no-cache"> <!-- Legacy HTTP 1.0 backward compatibility -->
+    <meta http-equiv="Expires" content="0"> <!-- Proxies -->
+    <link href="bulma.min.css" rel="stylesheet">
+    <script src="hostConfig.js"></script>
+    <script src="messagehost.js"></script>
+    <style>
+      #pasjsconsole {
+        border-style: solid;
+        border-width: 1px;
+        margin-left: 64px;
+        margin-right: 64px;
+      }
+    </style>
+  </head>
+<body>
+  <div class="container">
+  <h3 class="title is-3">Webassembly program output</h3>
+  <hr>
+  <div class="box">
+     <input class="input is-primary" type="text"  placeholder="Your message" id="edtMsg"/>
+     <button class="button is-primary"  id="btnSend">Send</button>
+  </div>
+  <div class="box">
+    <div id="pasjsconsole" >
+    </div>
+  </div>  
+  <div class="box">
+     <button class="button is-secondary"  id="btnSend2">Let Wasm Send</button>
+  </div>
+  <script>
+    rtl.showUncaughtExceptions=true;
+    rtl.run();
+  </script>
+</body>
+</html>

+ 100 - 0
demo/wasienv/messages/messagehost.lpi

@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CONFIG>
+  <ProjectOptions>
+    <Version Value="12"/>
+    <General>
+      <Flags>
+        <SaveOnlyProjectUnits Value="True"/>
+        <MainUnitHasCreateFormStatements Value="False"/>
+        <MainUnitHasTitleStatement Value="False"/>
+        <MainUnitHasScaledStatement Value="False"/>
+      </Flags>
+      <SessionStorage Value="InProjectDir"/>
+      <Title Value="messagehost"/>
+      <UseAppBundle Value="False"/>
+      <ResourceType Value="res"/>
+    </General>
+    <CustomData Count="4">
+      <Item0 Name="MaintainHTML" Value="1"/>
+      <Item1 Name="Pas2JSProject" Value="1"/>
+      <Item2 Name="PasJSLocation" Value="messagehost"/>
+      <Item3 Name="PasJSWebBrowserProject" Value="1"/>
+    </CustomData>
+    <BuildModes>
+      <Item Name="Default" Default="True"/>
+    </BuildModes>
+    <PublishOptions>
+      <Version Value="2"/>
+      <UseFileFilters Value="True"/>
+    </PublishOptions>
+    <RunParams>
+      <FormatVersion Value="2"/>
+    </RunParams>
+    <Units>
+      <Unit>
+        <Filename Value="messagehost.lpr"/>
+        <IsPartOfProject Value="True"/>
+        <UnitName Value="httphost"/>
+      </Unit>
+      <Unit>
+        <Filename Value="index.html"/>
+        <IsPartOfProject Value="True"/>
+        <CustomData Count="1">
+          <Item0 Name="PasJSIsProjectHTMLFile" Value="1"/>
+        </CustomData>
+      </Unit>
+      <Unit>
+        <Filename Value="hostconfig.js"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+      <Unit>
+        <Filename Value="../../Src/HTTP/pas2js/wasm.pas2js.httpapi.pas"/>
+        <IsPartOfProject Value="True"/>
+      </Unit>
+    </Units>
+  </ProjectOptions>
+  <CompilerOptions>
+    <Version Value="11"/>
+    <Target>
+      <Filename Value="messagehost"/>
+    </Target>
+    <SearchPaths>
+      <IncludeFiles Value="$(ProjOutDir)"/>
+      <UnitOutputDirectory Value="js"/>
+    </SearchPaths>
+    <Parsing>
+      <SyntaxOptions>
+        <AllowLabel Value="False"/>
+        <UseAnsiStrings Value="False"/>
+        <CPPInline Value="False"/>
+      </SyntaxOptions>
+    </Parsing>
+    <CodeGeneration>
+      <TargetOS Value="browser"/>
+    </CodeGeneration>
+    <Linking>
+      <Debugging>
+        <GenerateDebugInfo Value="False"/>
+        <DebugInfoType Value="dsDwarf3"/>
+        <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>

+ 115 - 0
demo/wasienv/messages/messagehost.lpr

@@ -0,0 +1,115 @@
+{
+    This file is part of the Free Component Library
+
+    Webassembly MessageChannel API - demo host program 
+    Copyright (c) 2025 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+program httphost;
+
+{$mode objfpc}
+{$modeswitch externalclass}
+
+uses
+  BrowserConsole, JS, Classes, SysUtils, WebOrWorker, Web, WasiEnv, WasiHostApp,
+  wasm.pas2js.messagechannelapi;
+
+Type
+  THostConfig = class external name 'Object' (TJSObject)
+    wasmFilename : String;
+  end;
+
+var
+  HostConfig : THostConfig; external name 'hostConfig';
+
+Type
+
+
+   { TMessageHostApplication }
+
+  TMessageHostApplication = class(TBrowserWASIHostApplication)
+  Private
+    edtMsg : TJSHTMLInputElement;
+    btnSend : TJSHTMLButtonElement;
+    btnSend2 : TJSHTMLButtonElement;
+    FChannelAPI : TMessageChannelAPI;
+    FChannel : TJSBroadcastChannel;
+    function DoHandleMessage(aEvent: TJSEvent): boolean;
+    function DoSendMessage(aEvent: TJSEvent): boolean;
+    function DoWasmSendMessage(aEvent: TJSEvent): boolean;
+  Public
+    constructor Create(aOwner : TComponent); override;
+    procedure DoRun; override;
+  end;
+
+function TMessageHostApplication.DoSendMessage(aEvent: TJSEvent): boolean;
+begin
+  FChannel.postMessage(edtMsg.value);
+end;
+
+function TMessageHostApplication.DoWasmSendMessage(aEvent: TJSEvent): boolean;
+type
+  TProcedure = procedure;
+var
+  proc : TProcedure;
+begin
+  Proc:=TProcedure(Exported['SendMessage']);
+  if assigned(Proc) then
+    proc;
+end;
+
+
+function TMessageHostApplication.DoHandleMessage(aEvent: TJSEvent): boolean;
+var
+  lMsg : TJSMessageEvent absolute aEvent;
+begin
+  Writeln(lMsg.Data);
+end;
+
+
+constructor TMessageHostApplication.Create(aOwner: TComponent);
+begin
+  inherited Create(aOwner);
+  FChannel:=TJSBroadcastChannel.new('some_channel');
+  FChannel.AddEventListener('message',@DoHandleMessage);
+  FChannelAPI:=TMessageChannelAPI.Create(WasiEnvironment);
+  RunEntryFunction:='_initialize';
+  edtMsg:=TJSHTMLInputElement(GetHTMLElement('edtMsg'));
+  btnSend:=TJSHTMLButtonElement(GetHTMLElement('btnSend'));
+  btnSend.AddEventListener('click',@DoSendMessage);
+  btnSend2:=TJSHTMLButtonElement(GetHTMLElement('btnSend2'));
+  btnSend2.AddEventListener('click',@DoWasmSendMessage);
+end;
+
+procedure TMessageHostApplication.DoRun;
+
+var
+  wasm : String;
+
+begin
+  Terminate;
+  if (HostConfig=undefined) and Assigned(HostConfig) and isString(HostConfig.wasmFilename) then
+    Wasm:=HostConfig.wasmFilename
+  else
+    begin
+    Wasm:=ParamStr(1);
+    if Wasm='' then
+      Wasm:='channeldemo.wasm';
+    end;
+  StartWebAssembly(Wasm, true);
+end;
+
+var
+  Application : TMessageHostApplication;
+begin
+  Application:=TMessageHostApplication.Create(nil);
+  Application.Initialize;
+  Application.Run;
+end.

+ 45 - 0
packages/wasm-utils/src/wasm.messagechannel.shared.pas

@@ -0,0 +1,45 @@
+{
+    This file is part of the Free Component Library
+
+    Webassembly Message channel API - shared constants 
+    Copyright (c) 2024 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit wasm.messagechannel.shared;
+
+interface
+
+type
+  TWasmMessageChannelResult = longint;
+  TWasmMessageChannelID = longint;
+  TWasmChannelType = (ctWorker,ctBroadcast);
+
+  
+const
+  WASMMSGCHANNEL_RESULT_SUCCESS         = 0;
+  WASMMSGCHANNEL_RESULT_INVALIDCHANNEL  = -1;
+  WASMMSGCHANNEL_RESULT_INVALIDDATALEN  = -2;
+  WASMMSGCHANNEL_RESULT_INVALIDTYPE     = -3;
+  WASMMSGCHANNEL_RESULT_UNSUPPORTEDTYPE = -4;
+
+
+const
+  MsgChannelExportName  = 'messagechannel';
+  MsgChannelFN_Allocate = 'messagechannel_allocate';
+  MsgChannelFN_DeAllocate = 'messagechannel_deallocate';
+  MsgChannelFN_SendUTF8 = 'messagechannel_send_utf8';
+  MsgChannelFN_SendUTF16 = 'messagechannel_send_utf16';
+  MsgChannelFN_Listen = 'messagechannel_listen';
+  MsgChannelFN_OnMessageUTF8 = 'messagechannel_onmesssage_callback_utf8';
+  MsgChannelFN_OnMessageUTF16 = 'messagechannel_onmesssage_callback_utf16';
+
+implementation
+
+end.

+ 333 - 0
packages/wasm-utils/src/wasm.pas2js.messagechannelapi.pas

@@ -0,0 +1,333 @@
+{
+    This file is part of the Free Component Library
+
+    Webassembly message channel API - WASM import API
+    Copyright (c) 2024 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit wasm.pas2js.messagechannelapi;
+
+interface
+
+uses js, sysutils, wasienv, wasm.messagechannel.shared, weborworker, contnrs;
+
+Type
+
+  { TWasmChannel }
+  TWasmOnChannelMessage = procedure(aSender : TObject; aID : TWasmMessageChannelID; aMsg : JSValue) of object;
+
+  TWasmChannel = class(TObject)
+  private
+    FChannelType: TWasmChannelType;
+    FID: TWasmMessageChannelID;
+    FOnMessage: TWasmOnChannelMessage;
+    procedure SetOnMessage(AValue: TWasmOnChannelMessage);
+  protected
+    procedure HandleMessage(aEvent: TJSEvent);
+    Procedure StartListening; virtual; abstract;
+  public
+    constructor create(aID : TWasmMessageChannelID; aType : TWasmChannelType);
+    Procedure SendMessage(Msg : JSValue); virtual; abstract;
+    property OnMessage : TWasmOnChannelMessage Read FOnMessage Write SetOnMessage;
+    property ChannelType : TWasmChannelType Read FChannelType;
+    property ID : TWasmMessageChannelID read FID;
+  end;
+
+  { TWasmBroadCastChannel }
+
+  TWasmBroadCastChannel = class(TWasmChannel)
+  Private
+    FChannel : TJSBroadcastChannel;
+  protected
+    procedure StartListening; override;
+  Public
+    constructor create(aID : TWasmMessageChannelID; const aName : string); reintroduce;
+    destructor destroy; override;
+    Procedure SendMessage(Msg : JSValue); override;
+    Property Channel : TJSBroadcastChannel Read FChannel;
+  end;
+
+//  TWasmWorkerChannel = class();
+
+  { TMessageChannelAPI }
+
+  TMessageChannelAPI = class(TImportExtension)
+  private
+    FChannels:TFPObjectHashTable;
+  protected
+    // internal methods
+    procedure DoOnChannelMessageUTF8(aSender: TObject; aID: TWasmMessageChannelID; aMsg: JSValue); virtual;
+    procedure DoOnChannelMessageUTF16(aSender: TObject; aID: TWasmMessageChannelID; aMsg: JSValue);virtual;
+    function FindChannel(aID: TWasmMessageChannelID): TWasmChannel;
+    procedure AddChannel(aChannel : TWasmChannel);
+    procedure RemoveChannel(aChannel : TWasmChannel);
+    function CreateChannel(aType : TWasmChannelType; aID: TWasmMessageChannelID; aName : String) : TWasmChannel; virtual;
+    // callable methods
+    function SendMessageUtf8(aID: TWasmMessageChannelID; aData: TWasmPointer; aDataLen: Longint; aDeserialize: Longint): TWasmMessageChannelResult;
+    function SendMessageUtf16(aID: TWasmMessageChannelID; aData: TWasmPointer; aDataCharLen: Longint; aDeserialize: Longint): TWasmMessageChannelResult;
+    function AllocateMessageChannel(aID: TWasmMessageChannelID; aType: Longint; aName: TWasmPointer; aNameLen: Longint): TWasmMessageChannelResult;
+    function DeAllocateMessageChannel(aID: TWasmMessageChannelID): TWasmMessageChannelResult;
+    function ListenToMessages(aID: TWasmMessageChannelID; aUseUTF16 : Integer): TWasmMessageChannelResult;
+  public
+    constructor Create(aEnv: TPas2JSWASIEnvironment); override;
+    procedure FillImportObject(aObject: TJSObject); override;
+    function ImportName: String; override;
+  end;
+
+implementation
+
+{ TWasmChannel }
+
+procedure TWasmChannel.SetOnMessage(AValue: TWasmOnChannelMessage);
+begin
+  if FOnMessage=AValue then Exit;
+  FOnMessage:=AValue;
+  if Assigned(FOnMessage) then
+    StartListening;
+end;
+
+
+constructor TWasmChannel.create(aID : TWasmMessageChannelID;aType: TWasmChannelType);
+begin
+  FID:=aID;
+  FChannelType:=aType;
+end;
+
+
+procedure TWasmChannel.HandleMessage(aEvent : TJSEvent);
+
+var
+  lEvent : TJSMessageEvent absolute aEvent;
+
+begin
+  if assigned(OnMessage) then
+    OnMessage(Self,ID,lEvent.Data);
+end;
+
+{ TWasmBroadCastChannel }
+
+procedure TWasmBroadCastChannel.StartListening;
+begin
+  FChannel.addEventListener('message',@HandleMessage);
+end;
+
+constructor TWasmBroadCastChannel.create(aID : TWasmMessageChannelID; const aName: string);
+begin
+  inherited create(aID,ctBroadcast);
+  FChannel:=TJSBroadcastChannel.New(aName);
+end;
+
+destructor TWasmBroadCastChannel.destroy;
+begin
+  FChannel.Close;
+  FChannel:=Nil;
+  inherited destroy;
+end;
+
+procedure TWasmBroadCastChannel.SendMessage(Msg: JSValue);
+begin
+  FChannel.postMessage(Msg);
+end;
+
+procedure TMessageChannelAPI.DoOnChannelMessageUTF8(aSender: TObject; aID: TWasmMessageChannelID; aMsg: JSValue);
+Type
+  TMsgProc = procedure(aID : TWasmMessageChannelID; aMsg : TWasmPointer; aMsgLen : Longint);
+
+var
+  lMsgProcExp : JSValue;
+  lMsgProc: TMsgProc absolute lMsgProcExp;
+  lMem : TWasmPointer;
+  lLen : Longint;
+  S : string;
+
+begin
+  lMsgProcExp:=InstanceExports[MsgChannelFN_OnMessageUTF8];
+  if not Assigned(lMsgProcExp) then
+    Exit;
+  S:=TJSJSON.stringify(aMsg);
+  lLen:=env.GetUTF8ByteLength(S);
+  lMem:=InstanceExports.AllocMem(lLen);
+  try
+    Env.SetUTF8StringInMem(lMem,lLen,S);
+    lMsgproc(aID,lMem,lLen);
+  finally
+    InstanceExports.freeMem(lMem);
+  end;
+end;
+
+procedure TMessageChannelAPI.DoOnChannelMessageUTF16(aSender: TObject; aID: TWasmMessageChannelID; aMsg: JSValue);
+Type
+  TMsgProc = procedure(aID : TWasmMessageChannelID; aMsg : TWasmPointer; aMsgLen : Longint);
+
+var
+  lMsgProcExp : JSValue;
+  lMsgProc: TMsgProc absolute lMsgProcExp;
+  lMem : TWasmPointer;
+  lLen : Longint;
+  S : string;
+
+begin
+  lMsgProcExp:=InstanceExports[MsgChannelFN_OnMessageUtf16];
+  if not Assigned(lMsgProcExp) then
+    Exit;
+  S:=TJSJSON.stringify(aMsg);
+  lLen:=Length(S)*2;
+  lMem:=InstanceExports.AllocMem(lLen);
+  try
+    Env.SetUTF16StringInMem(lMem,S);
+    lMsgproc(aID,lMem,lLen);
+  finally
+    InstanceExports.freeMem(lMem);
+  end;
+end;
+
+{ TMessageChannelAPI }
+function TMessageChannelAPI.FindChannel(aID : TWasmMessageChannelID) : TWasmChannel;
+
+begin
+  Result:=TWasmChannel(FChannels.Items[IntToStr(aID)]);
+end;
+
+procedure TMessageChannelAPI.AddChannel(aChannel: TWasmChannel);
+begin
+  FChannels.Add(IntToStr(aChannel.ID),aChannel);
+end;
+
+procedure TMessageChannelAPI.RemoveChannel(aChannel: TWasmChannel);
+begin
+  FChannels.Delete(IntToStr(aChannel.ID));
+end;
+
+function TMessageChannelAPI.CreateChannel(aType: TWasmChannelType; aID: TWasmMessageChannelID; aName: String): TWasmChannel;
+begin
+  if aType=ctBroadcast then
+    Result:=TWasmBroadCastChannel.Create(aID,aName)
+  else
+    Result:=Nil;
+end;
+
+function TMessageChannelAPI.DeAllocateMessageChannel(aID : TWasmMessageChannelID) : TWasmMessageChannelResult;
+var
+  lChannel : TWasmChannel;
+begin
+  lChannel:=FindChannel(aID);
+  if (lChannel=Nil) then
+    exit(WASMMSGCHANNEL_RESULT_INVALIDCHANNEL);
+  RemoveChannel(lChannel);
+  Result:=WASMMSGCHANNEL_RESULT_SUCCESS;
+end;
+
+function TMessageChannelAPI.ListenToMessages(aID: TWasmMessageChannelID;  aUseUTF16 : Integer): TWasmMessageChannelResult;
+var
+  lChannel : TWasmChannel;
+begin
+  lChannel:=FindChannel(aID);
+  if (lChannel=Nil) then
+    exit(WASMMSGCHANNEL_RESULT_INVALIDCHANNEL);
+  if aUseUTF16=0 then
+    lChannel.OnMessage:=@DoOnChannelMessageUTF8
+  else
+    lChannel.OnMessage:=@DoOnChannelMessageUTF16;
+end;
+
+constructor TMessageChannelAPI.Create(aEnv: TPas2JSWASIEnvironment);
+begin
+  FChannels:=TFPObjectHashTable.Create(True);
+  inherited Create(aEnv);
+end;
+
+function TMessageChannelAPI.AllocateMessageChannel(aID : TWasmMessageChannelID; aType : Longint; aName : TWasmPointer; aNameLen : Longint) : TWasmMessageChannelResult;
+var
+  lType : TWasmChannelType;
+  lName : String;
+  lChannel : TWasmChannel;
+begin
+  if (aType<0) or (aType>Ord(High(TWasmChannelType))) then
+    Exit(WASMMSGCHANNEL_RESULT_INVALIDTYPE);
+  lType:=TWasmChannelType(aType);
+  lChannel:=FindChannel(aID);
+  if (lChannel<>Nil) then
+    exit(WASMMSGCHANNEL_RESULT_INVALIDCHANNEL);
+  if (aNameLen<0) then
+    exit(WASMMSGCHANNEL_RESULT_INVALIDDATALEN);
+  lName:=Env.GetUTF8StringFromMem(aName,aNameLen);
+  lChannel:=CreateChannel(lType,aID,lName);
+  if (lChannel=Nil) then
+    exit(WASMMSGCHANNEL_RESULT_UNSUPPORTEDTYPE);
+  AddChannel(lChannel);
+  Result:=WASMMSGCHANNEL_RESULT_SUCCESS;
+end;
+
+function TMessageChannelAPI.SendMessageUtf8(aID: TWasmMessageChannelID; aData: TWasmPointer; aDataLen: Longint;
+  aDeserialize: Longint): TWasmMessageChannelResult;
+var
+  lStringData : String;
+  lData : JSValue;
+  lChannel : TWasmChannel;
+begin
+  lChannel:=FindChannel(aID);
+  if (lChannel=Nil) then
+    exit(WASMMSGCHANNEL_RESULT_INVALIDCHANNEL);
+  if (aDataLen<0) then
+    exit(WASMMSGCHANNEL_RESULT_INVALIDDATALEN);
+  lStringData:=Env.GetUTF8StringFromMem(aData,aDataLen);
+  if aDeserialize=0 then
+    lData:=lStringData
+  else
+    lData:=TJSJSON.parse(LStringData);
+  try
+    lChannel.SendMessage(lData);
+  except
+    console.error(Format('Error sending message data to channel %d: %s',[aID,lStringData]));
+  end;
+  Result:=WASMMSGCHANNEL_RESULT_SUCCESS;
+end;
+
+function TMessageChannelAPI.SendMessageUtf16(aID: TWasmMessageChannelID; aData: TWasmPointer; aDataCharLen: Longint;
+  aDeserialize: Longint): TWasmMessageChannelResult;
+var
+  lStringData : String;
+  lData : JSValue;
+  lChannel : TWasmChannel;
+begin
+  lChannel:=FindChannel(aID);
+  if (lChannel=Nil) then
+    exit(WASMMSGCHANNEL_RESULT_INVALIDCHANNEL);
+  if (aDataCharLen<0) then
+    exit(WASMMSGCHANNEL_RESULT_INVALIDDATALEN);
+  lStringData:=Env.GetUTF16StringFromMem(aData,aDataCharLen);
+  if aDeserialize=0 then
+    lData:=lStringData
+  else
+    lData:=TJSJSON.parse(LStringData);
+  try
+    lChannel.SendMessage(lData);
+  except
+    console.error(Format('Error sending message data to channel %d: %s',[aID,lStringData]));
+  end;
+  Result:=WASMMSGCHANNEL_RESULT_SUCCESS;
+end;
+
+
+procedure TMessageChannelAPI.FillImportObject(aObject: TJSObject);
+begin
+  aObject[MsgChannelFN_Allocate]:=@AllocateMessageChannel;
+  aObject[MsgChannelFN_DeAllocate]:=@DeAllocateMessageChannel;
+  aObject[MsgChannelFN_SendUtf8]:=@SendMessageUtf8;
+  aObject[MsgChannelFN_SendUtf16]:=@SendMessageUtf16;
+  aObject[MsgChannelFN_Listen]:=@ListenToMessages;
+end;
+
+function TMessageChannelAPI.ImportName: String;
+begin
+  Result:=MsgChannelExportName;
+end;
+
+end.

+ 61 - 0
packages/wasm-utils/src/wasm.pas2js.messagechannelapi.worker.pas

@@ -0,0 +1,61 @@
+{
+    This file is part of the Free Component Library
+
+    Webassembly Message channel API - worker implementation
+    Copyright (c) 2024 by Michael Van Canneyt [email protected]
+
+    See the file COPYING.FPC, included in this distribution,
+    for details about the copyright.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ **********************************************************************}
+unit wasm.pas2js.messagechannelapi.worker;
+
+{$mode ObjFPC}
+
+interface
+
+uses
+  SysUtils, wasm.pas2js.messagechannelapi,wasm.messagechannel.shared, webworker;
+
+Type
+  TWasmWorkerChannel = class(TWasmChannel)
+  public
+    constructor create(aID: TWasmMessageChannelID);
+    procedure SendMessage(Msg: JSValue); override;
+  end;
+
+  TWorkerMessageChannelAPI = Class(TMessageChannelAPI)
+  Protected
+    function CreateChannel(aType: TWasmChannelType; aID: TWasmMessageChannelID; aName: String): TWasmChannel; override;
+  end;
+
+implementation
+
+{ TWasmWorkerChannel }
+
+constructor TWasmWorkerChannel.create(aID: TWasmMessageChannelID);
+begin
+  inherited create(aID,ctWorker);
+end;
+
+procedure TWasmWorkerChannel.SendMessage(Msg: JSValue);
+begin
+  self_.postMessage(Msg);
+end;
+
+{ TWorkerMessageChannelAPI }
+
+function TWorkerMessageChannelAPI.CreateChannel(aType: TWasmChannelType; aID: TWasmMessageChannelID; aName: String): TWasmChannel;
+begin
+  if aType=ctWorker then
+    Result:=TWasmWorkerChannel.Create(aID)
+  else
+    Result:=inherited CreateChannel(aType, aID, aName);
+end;
+
+end.
+

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio