Rtl.BrowserLoadHelper.pas 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. {
  2. This file is part of the Pas2JS run time library.
  3. Copyright (c) 2023 by Michael Van Canneyt
  4. Loader helper for TStringList, usable in the browser.
  5. See the file COPYING.FPC, included in this distribution,
  6. for details about the copyright.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. **********************************************************************}
  11. {$IFNDEF FPC_DOTTEDUNITS}
  12. unit Rtl.BrowserLoadHelper;
  13. {$ENDIF}
  14. {$mode objfpc}
  15. interface
  16. uses
  17. {$IFDEF FPC_DOTTEDUNITS}
  18. System.Classes, System.SysUtils, JSApi.JS, BrowserApi.Web;
  19. {$ELSE}
  20. Classes, SysUtils, JS, Web;
  21. {$ENDIF}
  22. Type
  23. { TBrowserLoadHelper }
  24. TBrowserLoadHelper = Class (TLoadHelper)
  25. Public
  26. Class Procedure LoadText(aURL : String; aSync : Boolean; aOnLoaded : TTextLoadedCallBack; aOnError : TErrorCallBack); override;
  27. Class Procedure LoadBytes(aURL : String; aSync : Boolean; aOnLoaded : TBytesLoadedCallBack; aOnError : TErrorCallBack); override;
  28. end;
  29. implementation
  30. { TBrowserLoadHelper }
  31. class procedure TBrowserLoadHelper.LoadText(aURL: String; aSync: Boolean; aOnLoaded: TTextLoadedCallBack; aOnError: TErrorCallBack);
  32. function doFetchOK(response : JSValue) : JSValue;
  33. var
  34. Res : TJSResponse absolute response;
  35. begin
  36. Result:=False;
  37. If (Res.status<>200) then
  38. begin
  39. If Assigned(aOnError) then
  40. aOnError('Error '+IntToStr(Res.Status)+ ': '+Res.StatusText)
  41. end
  42. else
  43. Res.Text._then(
  44. function (value : JSValue) : JSValue
  45. begin
  46. aOnLoaded(String(value));
  47. end
  48. );
  49. end;
  50. function doFetchFail(response : JSValue) : JSValue;
  51. begin
  52. Result:=False;
  53. aOnError('Error 999: unknown error: '+TJSJSON.Stringify(response));
  54. end;
  55. begin
  56. if ASync then
  57. Window.Fetch(aURl)._then(@DoFetchOK).catch(@DoFetchFail)
  58. else
  59. With TJSXMLHttpRequest.new do
  60. begin
  61. open('GET', aURL, False);
  62. AddEventListener('load',Procedure (oEvent: JSValue)
  63. begin
  64. aOnLoaded(responseText);
  65. end
  66. );
  67. AddEventListener('error',Procedure (oEvent: JSValue)
  68. begin
  69. if Assigned(aOnError) then
  70. aOnError(TJSError(oEvent).Message);
  71. end
  72. );
  73. send();
  74. end;
  75. end;
  76. class procedure TBrowserLoadHelper.LoadBytes(aURL: String; aSync: Boolean; aOnLoaded: TBytesLoadedCallBack; aOnError: TErrorCallBack);
  77. function doFetchFail(response : JSValue) : JSValue;
  78. begin
  79. Result:=False;
  80. if assigned(aOnError) then
  81. if isObject(Response) and (TJSObject(Response) is TJSError) then
  82. aOnError('Error 999: '+TJSError(Response).Message)
  83. else
  84. aOnError('Error 999: unknown error');
  85. end;
  86. function doFetchOK(response : JSValue) : JSValue;
  87. var
  88. Res : TJSResponse absolute response;
  89. begin
  90. Result:=False;
  91. If (Res.status<>200) then
  92. begin
  93. If Assigned(aOnError) then
  94. aOnError('Error '+IntToStr(Res.Status)+ ': '+Res.StatusText)
  95. end
  96. else
  97. Res.Blob._then(
  98. function (value : JSValue) : JSValue
  99. begin
  100. TJSBlob(Value).ArrayBuffer._then(function(arr : JSValue) : JSValue
  101. begin
  102. aOnLoaded(TJSArrayBuffer(arr))
  103. end
  104. ).Catch(@DoFetchFail);
  105. end
  106. );
  107. end;
  108. function StringToArrayBuffer(str : string) : TJSArrayBuffer;
  109. Var
  110. i,l : Integer;
  111. begin
  112. L:=Length(str);
  113. Result:=TJSArrayBuffer.New(l*2); // 2 bytes for each char
  114. With TJSUint16Array.New(Result) do
  115. for i:=1 to L do
  116. Values[i-1]:=Ord(Str[i]);
  117. end;
  118. begin
  119. if ASync then
  120. Window.Fetch(aURl)._then(@DoFetchOK).catch(@DoFetchFail)
  121. else
  122. With TJSXMLHttpRequest.new do
  123. begin
  124. open('GET', aURL, False);
  125. AddEventListener('load',Procedure (oEvent: JSValue)
  126. begin
  127. if (Status<>200) then
  128. begin
  129. if assigned(aOnError) then
  130. aOnError('Error '+IntToStr(Status)+ ': '+StatusText)
  131. end
  132. else
  133. aOnLoaded(StringToArrayBuffer(responseText));
  134. end
  135. );
  136. AddEventListener('error',Procedure (oEvent: JSValue)
  137. begin
  138. if Assigned(aOnError) then
  139. aOnError(TJSError(oEvent).Message);
  140. end
  141. );
  142. send();
  143. end;
  144. end;
  145. initialization
  146. SetLoadHelperClass(TBrowserLoadHelper);
  147. end.