after update D12 to D13, XData 5.19 to 5.22, WebCore 2.7 to 2.9

After updating my entire system,
I get an error in the JavaScript console.
See image.

At this point, I'm reading a config file for establishing my communication with the servers.

And here's the source code:

First my code to read: (sng.AppConfig.pas:149:28)

function WebAppLoadConfigAsync: TAppConfig;
var
  Conn: TXDataWebConnection;
  Response: IHttpResponse;
  Obj: TJSObject;
begin
  Result := nil;
  Conn := TXDataWebConnection.Create(nil);
  try
    Response := Await( Conn.SendRequestAsync( THttpRequest.Create( cPathToConfig + cConfigFile)));  //  <-- Errorline 149
    if Response.StatusCode = _http_200_Ok then begin
      Obj := TJSJSON.parseObject( Response.ContentAsText);
      Result := TAppConfig.Create;
      if JS.toString(  Obj[ cIniSystemScheme ]) <> '' then Result.FSystemScheme := JS.toString(  Obj[ cIniSystemScheme ]);
      if JS.toString(  Obj[ cIniSystemHost   ]) <> '' then Result.FSystemHost   := JS.toString(  Obj[ cIniSystemHost   ]);
      if JS.toInteger( Obj[ cIniRESTPort     ]) <> 0  then Result.FRESTPort     := JS.toInteger( Obj[ cIniRESTPort     ]);
      if JS.toString(  Obj[ cIniBasisPath    ]) <> '' then Result.FBasisPath    := JS.toString(  Obj[ cIniBasisPath    ]);
    end;
  finally
    Conn.Free;
  end;
end;

Then the function in XData.Web.Connection (XData.Web.Connection:509:7)

function TXDataWebConnection.SendRequestAsync(
  Request: IHttpRequest): IHttpResponse;
var
  Promise: TJSPromise;
begin
  Promise := TJSPromise.new(
    procedure(resolve, reject: TJSPromiseResolver)
    begin
      SendRequest(
        Request,
        procedure(Response: IHttpResponse)
        begin
          Response._AddRef;
          resolve(Response);
        end,
        procedure
        begin
          reject(Exception.Create('Request error: ' + Request.Uri));
        end
      );
    end
  );
  Exit(Promise);   // <-- Errorline 509
end;

And here are the lines in rtl.js (rtl.js:856:1)

We've had several problems with "Promise" after the update (see WebCore).
Could this be related?
Everything was working fine before.

Possibly. We are investigating. Do you have the links for the support topics where you reported issues about Promises?

Yes, here is a link

The issue with promises used as parameter for methods was a compile time issue. I cannot see this being related to a runtime JavaScript issue.
Although I can also not directly see a relationship to an issue with _AddRef() calls, we did this week a fix in rtl.js you might test with to see if it helps.
rtl.zip (11.8 KB)

Hello Bruno,

This fix seems to work for this issue:


This error, however, refers to a call in XData. And the problem still exists.
But I'm not sure if it has something to do with promises or is just a side effect.

I found something, but it doesn't resolve the error.
Lines 206-209 in XData.Web.Connection.pas
I had: Req.Content = undefined

Old:

  if not Js.IsNull(Req.Content) then
    Xhr.send(Req.Content)
  else
    Xhr.send;

Change:

  if not Js.IsNull(Req.Content) and not Js.isUndefined(Req.Content) then
    Xhr.send(Req.Content)
  else
    Xhr.send;

I suspect this is the cause:

Returning the promise in Exit(Promise) causes the error in the async functions.

Is pas2js already integrated in version 3.2.0?
Is it possible to go back to 3.0.1?

I can no longer use the package (WebCore / XData) at the moment.

I've now temporarily fixed the error.
I've modified the SendRequestAsync function in XData.Web.Connection.pas as follows:

//function TXDataWebConnection.SendRequestAsync( Request: IHttpRequest): IHttpResponse;
function TXDataWebConnection.SendRequestAsync( Request: IHttpRequest): TJSPromise;
//var
//  Promise: TJSPromise;
begin
  //Promise := TJSPromise.new(
  Result := TJSPromise.new(
    procedure(resolve, reject: TJSPromiseResolver)
    begin
      SendRequest(
        Request,
        procedure(Response: IHttpResponse)
        begin
          if Assigned(Response) then
            Response._AddRef;
          //resolve(Response);
          resolve(JSValue(Response));
        end,
        procedure
        begin
          reject(Exception.Create('Request error: ' + Request.Uri));
        end
      );
    end
  );
  //Exit(Promise);
end;

Due to the stricter validation, the function now returns a TJSPromise (internally as a JSValue).

I had to replace my call

Response := TAwait.Exec<IHttpResponse>( Conn.SendRequestAsync( THttpRequest.Create( myFile)));
// Wrong number of parameters specified for call to "function await(aType,TJSPromise):aType

with this one

Response := await( IHttpResponse,  Conn.SendRequestAsync( THttpRequest.Create( myFile)));

So it works again.

I hope this was helpful and I look forward to an update :grinning_face:

The latest pas2js transpiler is more strict wrt async functions and check more strictly that these return a TJSPromise. So, the change to make TJSPromise the result type is correct. With TAwait, this can be caught with:

Response := TAwait.ExecP<IHttpResponse>( Conn.SendRequestAsync( THttpRequest.Create( myFile)));

Also, to check content is defined, a better solution is:

if Js.isDefined(Req.Content) then
    Xhr.send(Req.Content)
  else
    Xhr.send;