mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 20:09:27 +02:00
pastojs: await with one param must be async function
git-svn-id: trunk@47895 -
This commit is contained in:
parent
edfbf2ce30
commit
8eafcd9490
@ -3544,7 +3544,8 @@ begin
|
|||||||
' s[9+1]:=''b'';',
|
' s[9+1]:=''b'';',
|
||||||
' s[10]:='''''''';',
|
' s[10]:='''''''';',
|
||||||
' s[11]:=^g;',
|
' s[11]:=^g;',
|
||||||
' s[12]:=^H;']);
|
' s[12]:=^H;',
|
||||||
|
'']);
|
||||||
ParseProgram;
|
ParseProgram;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -3622,6 +3623,7 @@ begin
|
|||||||
' m=low(char)+high(char);',
|
' m=low(char)+high(char);',
|
||||||
' n = string(''A'');',
|
' n = string(''A'');',
|
||||||
' o = UnicodeString(''A'');',
|
' o = UnicodeString(''A'');',
|
||||||
|
//' p = ^C''bird'';',
|
||||||
'begin']);
|
'begin']);
|
||||||
ParseProgram;
|
ParseProgram;
|
||||||
CheckResolverUnexpectedHints;
|
CheckResolverUnexpectedHints;
|
||||||
|
@ -2399,6 +2399,7 @@ const
|
|||||||
TempRefSetPathName = 's';
|
TempRefSetPathName = 's';
|
||||||
TempRefParamName = 'a';
|
TempRefParamName = 'a';
|
||||||
IdentChars = ['0'..'9', 'A'..'Z', 'a'..'z','_'];
|
IdentChars = ['0'..'9', 'A'..'Z', 'a'..'z','_'];
|
||||||
|
AwaitSignature2 = 'function await(aType,TJSPromise):aType';
|
||||||
|
|
||||||
function CodePointToJSString(u: longword): TJSString;
|
function CodePointToJSString(u: longword): TJSString;
|
||||||
begin
|
begin
|
||||||
@ -5956,12 +5957,10 @@ end;
|
|||||||
|
|
||||||
function TPas2JSResolver.BI_AWait_OnGetCallCompatibility(
|
function TPas2JSResolver.BI_AWait_OnGetCallCompatibility(
|
||||||
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
Proc: TResElDataBuiltInProc; Expr: TPasExpr; RaiseOnError: boolean): integer;
|
||||||
// await(T; p: TJSPromise): T;
|
// await(T; p: TJSPromise): T
|
||||||
|
// await(T; jsvalue): T
|
||||||
|
// await(AsyncFuncWithResultT): T
|
||||||
// await(AsyncProc);
|
// await(AsyncProc);
|
||||||
// await(Proc);
|
|
||||||
// await(const Expr: T): T
|
|
||||||
const
|
|
||||||
Signature2 = 'function await(aType,TJSPromise):aType';
|
|
||||||
var
|
var
|
||||||
Params: TParamsExpr;
|
Params: TParamsExpr;
|
||||||
Param: TPasExpr;
|
Param: TPasExpr;
|
||||||
@ -5991,6 +5990,48 @@ begin
|
|||||||
// must be the only parameter
|
// must be the only parameter
|
||||||
Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
|
Result:=CheckBuiltInMaxParamCount(Proc,Params,1,RaiseOnError);
|
||||||
if Result=cIncompatible then exit;
|
if Result=cIncompatible then exit;
|
||||||
|
|
||||||
|
TypeEl:=ParamResolved.LoTypeEl;
|
||||||
|
if (ParamResolved.IdentEl is TPasResultElement) then
|
||||||
|
begin
|
||||||
|
// await(AsyncFuncCall)
|
||||||
|
if not TPasFunctionType(ParamResolved.IdentEl.Parent).IsAsync then
|
||||||
|
begin
|
||||||
|
{$IFDEF VerbosePas2JS}
|
||||||
|
writeln('TPas2JSResolver.BI_AWait_OnGetCallCompatibility ',GetResolverResultDbg(ParamResolved));
|
||||||
|
{$ENDIF}
|
||||||
|
if RaiseOnError then
|
||||||
|
RaiseMsg(20201229232446,nXExpectedButYFound,sXExpectedButYFound,['async function',GetResolverResultDescription(ParamResolved)],Expr)
|
||||||
|
else
|
||||||
|
exit(cIncompatible);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else if (ParamResolved.BaseType=btContext)
|
||||||
|
and (TypeEl is TPasProcedureType) then
|
||||||
|
begin
|
||||||
|
// await(AsyncFuncTypeVar)
|
||||||
|
if not TPasProcedureType(TypeEl).IsAsync then
|
||||||
|
begin
|
||||||
|
{$IFDEF VerbosePas2JS}
|
||||||
|
writeln('TPas2JSResolver.BI_AWait_OnGetCallCompatibility ',GetResolverResultDbg(ParamResolved));
|
||||||
|
{$ENDIF}
|
||||||
|
if RaiseOnError then
|
||||||
|
RaiseMsg(20201229232541,nXExpectedButYFound,sXExpectedButYFound,['async function',GetResolverResultDescription(ParamResolved)],Expr)
|
||||||
|
else
|
||||||
|
exit(cIncompatible);
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{$IFDEF VerbosePas2JS}
|
||||||
|
writeln('TPas2JSResolver.BI_AWait_OnGetCallCompatibility ',GetResolverResultDbg(ParamResolved));
|
||||||
|
{$ENDIF}
|
||||||
|
if RaiseOnError then
|
||||||
|
RaiseMsg(20201229224920,nXExpectedButYFound,sXExpectedButYFound,['async function',GetResolverResultDescription(ParamResolved)],Expr)
|
||||||
|
else
|
||||||
|
exit(cIncompatible);
|
||||||
|
end;
|
||||||
|
|
||||||
end
|
end
|
||||||
else if ParamResolved.BaseType=btProc then
|
else if ParamResolved.BaseType=btProc then
|
||||||
begin
|
begin
|
||||||
@ -6028,7 +6069,7 @@ begin
|
|||||||
begin
|
begin
|
||||||
if RaiseOnError then
|
if RaiseOnError then
|
||||||
RaiseMsg(20200520090749,nWrongNumberOfParametersForCallTo,
|
RaiseMsg(20200520090749,nWrongNumberOfParametersForCallTo,
|
||||||
sWrongNumberOfParametersForCallTo,[Signature2],Params);
|
sWrongNumberOfParametersForCallTo,[AwaitSignature2],Params);
|
||||||
exit(cIncompatible);
|
exit(cIncompatible);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -6062,14 +6103,21 @@ begin
|
|||||||
exit(CheckRaiseTypeArgNo(20200520091707,2,Param,Param2Resolved,
|
exit(CheckRaiseTypeArgNo(20200520091707,2,Param,Param2Resolved,
|
||||||
'instance of TJSPromise',RaiseOnError));
|
'instance of TJSPromise',RaiseOnError));
|
||||||
|
|
||||||
if (Param2Resolved.BaseType<>btContext)
|
if (Param2Resolved.BaseType=btContext)
|
||||||
or not (Param2Resolved.LoTypeEl is TPasClassType)
|
and (Param2Resolved.LoTypeEl is TPasClassType)
|
||||||
or not IsExternalClass_Name(TPasClassType(Param2Resolved.LoTypeEl),'Promise') then
|
and IsExternalClass_Name(TPasClassType(Param2Resolved.LoTypeEl),'Promise') then
|
||||||
exit(CheckRaiseTypeArgNo(20200520091707,2,Param,Param2Resolved,
|
// await(T,aPromise)
|
||||||
|
else if IsJSBaseType(Param2Resolved,pbtJSValue) then
|
||||||
|
// await(T,jsvalue)
|
||||||
|
else if (Param2Resolved.IdentEl is TPasArgument)
|
||||||
|
and (Param2Resolved.LoTypeEl=nil) then
|
||||||
|
// await(T,UntypedArg)
|
||||||
|
else
|
||||||
|
exit(CheckRaiseTypeArgNo(20200520091708,2,Param,Param2Resolved,
|
||||||
'TJSPromise',RaiseOnError));
|
'TJSPromise',RaiseOnError));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError,Signature2);
|
Result:=CheckBuiltInMaxParamCount(Proc,Params,2,RaiseOnError,AwaitSignature2);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -6084,11 +6132,18 @@ begin
|
|||||||
Param:=Params.Params[0];
|
Param:=Params.Params[0];
|
||||||
if length(Params.Params)=1 then
|
if length(Params.Params)=1 then
|
||||||
begin
|
begin
|
||||||
// await(expr)
|
// await(AsyncFuncCall)
|
||||||
if CheckCallAsyncFuncResult(Param,ResolvedEl) then
|
if CheckCallAsyncFuncResult(Param,ResolvedEl) then
|
||||||
|
begin
|
||||||
// await(CallAsynFuncResultT): T
|
// await(CallAsynFuncResultT): T
|
||||||
|
if (ResolvedEl.BaseType=btContext)
|
||||||
|
and (ResolvedEl.LoTypeEl is TPasClassType)
|
||||||
|
and IsExternalClass_Name(TPasClassType(ResolvedEl.LoTypeEl),'Promise') then
|
||||||
|
// async function returns a promise, await resolve all promises -> need final type as first param
|
||||||
|
RaiseMsg(20201229235932,nWrongNumberOfParametersForCallTo,
|
||||||
|
sWrongNumberOfParametersForCallTo,[AwaitSignature2],Param);
|
||||||
exit;
|
exit;
|
||||||
// await(expr:T):T
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
@ -883,8 +883,11 @@ type
|
|||||||
Procedure TestAwait_NonPromiseWithTypeFail;
|
Procedure TestAwait_NonPromiseWithTypeFail;
|
||||||
Procedure TestAwait_AsyncCallTypeMismatch;
|
Procedure TestAwait_AsyncCallTypeMismatch;
|
||||||
Procedure TestAWait_OutsideAsyncFail;
|
Procedure TestAWait_OutsideAsyncFail;
|
||||||
Procedure TestAWait_Result;
|
Procedure TestAWait_IntegerFail;
|
||||||
Procedure TestAWait_ExternalClassPromise;
|
Procedure TestAWait_ExternalClassPromise;
|
||||||
|
Procedure TestAWait_JSValue;
|
||||||
|
Procedure TestAWait_Result;
|
||||||
|
Procedure TestAWait_ResultPromiseMissingTypeFail;
|
||||||
Procedure TestAsync_AnonymousProc;
|
Procedure TestAsync_AnonymousProc;
|
||||||
Procedure TestAsync_ProcType;
|
Procedure TestAsync_ProcType;
|
||||||
Procedure TestAsync_ProcTypeAsyncModMismatchFail;
|
Procedure TestAsync_ProcTypeAsyncModMismatchFail;
|
||||||
@ -32619,48 +32622,21 @@ begin
|
|||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestAWait_Result;
|
procedure TTestModule.TestAWait_IntegerFail;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
Add([
|
Add([
|
||||||
'{$modeswitch externalclass}',
|
'function Run: word;',
|
||||||
'type',
|
|
||||||
' TJSPromise = class external name ''Promise''',
|
|
||||||
' end;',
|
|
||||||
'function Crawl(d: double = 1.3): word; ',
|
|
||||||
'begin',
|
'begin',
|
||||||
'end;',
|
'end;',
|
||||||
'function Run(d: double = 1.6): word; async;',
|
'procedure Fly(w: word); async;',
|
||||||
'begin',
|
'begin',
|
||||||
' Result:=await(1);',
|
' await(Run());',
|
||||||
' Result:=await(Crawl);',
|
|
||||||
' Result:=await(Crawl(4.5));',
|
|
||||||
' Result:=await(Run);',
|
|
||||||
' Result:=await(Run(6.7));',
|
|
||||||
'end;',
|
'end;',
|
||||||
'begin',
|
'begin',
|
||||||
' Run(1);']);
|
' Fly(1);']);
|
||||||
|
SetExpectedPasResolverError('async function expected, but Result:Word found',nXExpectedButYFound);
|
||||||
ConvertProgram;
|
ConvertProgram;
|
||||||
CheckSource('TestAWait_Result',
|
|
||||||
LinesToStr([ // statements
|
|
||||||
'this.Crawl = function (d) {',
|
|
||||||
' var Result = 0;',
|
|
||||||
' return Result;',
|
|
||||||
'};',
|
|
||||||
'this.Run = async function (d) {',
|
|
||||||
' var Result = 0;',
|
|
||||||
' Result = await 1;',
|
|
||||||
' Result = await $mod.Crawl(1.3);',
|
|
||||||
' Result = await $mod.Crawl(4.5);',
|
|
||||||
' Result = await $mod.Run(1.6);',
|
|
||||||
' Result = await $mod.Run(6.7);',
|
|
||||||
' return Result;',
|
|
||||||
'};',
|
|
||||||
'']),
|
|
||||||
LinesToStr([
|
|
||||||
'$mod.Run(1);'
|
|
||||||
]));
|
|
||||||
SetExpectedPasResolverError('Await without promise',nAwaitWithoutPromise);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestAWait_ExternalClassPromise;
|
procedure TTestModule.TestAWait_ExternalClassPromise;
|
||||||
@ -32723,6 +32699,110 @@ begin
|
|||||||
CheckResolverUnexpectedHints();
|
CheckResolverUnexpectedHints();
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestAWait_JSValue;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'{$modeswitch externalclass}',
|
||||||
|
'type',
|
||||||
|
' TJSPromise = class external name ''Promise''',
|
||||||
|
' end;',
|
||||||
|
'function Fly(w: word): jsvalue; async;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'function Run(d: jsvalue; var e): word; async;',
|
||||||
|
'begin',
|
||||||
|
' Result:=await(word,d);', // promise needs type
|
||||||
|
' d:=await(Fly(4));', // async non promise must omit the type
|
||||||
|
' Result:=await(word,e);', // promise needs type
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
'']);
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestAWait_JSValue',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.Fly = async function (w) {',
|
||||||
|
' var Result = undefined;',
|
||||||
|
' return Result;',
|
||||||
|
'};',
|
||||||
|
'this.Run = async function (d, e) {',
|
||||||
|
' var Result = 0;',
|
||||||
|
' Result = await d;',
|
||||||
|
' d = await $mod.Fly(4);',
|
||||||
|
' Result = await e.get();',
|
||||||
|
' return Result;',
|
||||||
|
'};',
|
||||||
|
'']),
|
||||||
|
LinesToStr([
|
||||||
|
]));
|
||||||
|
CheckResolverUnexpectedHints();
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestAWait_Result;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'{$modeswitch externalclass}',
|
||||||
|
'type',
|
||||||
|
' TJSPromise = class external name ''Promise''',
|
||||||
|
' end;',
|
||||||
|
'function Crawl(d: double = 1.3): TJSPromise; ',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'function Run(d: double = 1.6): word; async;',
|
||||||
|
'begin',
|
||||||
|
' Result:=await(word,Crawl);',
|
||||||
|
' Result:=await(word,Crawl(4.5));',
|
||||||
|
' Result:=await(Run);',
|
||||||
|
' Result:=await(Run(6.7));',
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
' Run(1);']);
|
||||||
|
ConvertProgram;
|
||||||
|
CheckSource('TestAWait_Result',
|
||||||
|
LinesToStr([ // statements
|
||||||
|
'this.Crawl = function (d) {',
|
||||||
|
' var Result = null;',
|
||||||
|
' return Result;',
|
||||||
|
'};',
|
||||||
|
'this.Run = async function (d) {',
|
||||||
|
' var Result = 0;',
|
||||||
|
' Result = await $mod.Crawl(1.3);',
|
||||||
|
' Result = await $mod.Crawl(4.5);',
|
||||||
|
' Result = await $mod.Run(1.6);',
|
||||||
|
' Result = await $mod.Run(6.7);',
|
||||||
|
' return Result;',
|
||||||
|
'};',
|
||||||
|
'']),
|
||||||
|
LinesToStr([
|
||||||
|
'$mod.Run(1);'
|
||||||
|
]));
|
||||||
|
CheckResolverUnexpectedHints();
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TTestModule.TestAWait_ResultPromiseMissingTypeFail;
|
||||||
|
begin
|
||||||
|
StartProgram(false);
|
||||||
|
Add([
|
||||||
|
'{$mode objfpc}',
|
||||||
|
'{$modeswitch externalclass}',
|
||||||
|
'type',
|
||||||
|
' TJSPromise = class external name ''Promise''',
|
||||||
|
' end;',
|
||||||
|
'function Run: TJSPromise; async;',
|
||||||
|
'begin',
|
||||||
|
'end;',
|
||||||
|
'procedure Fly(w: word); async;',
|
||||||
|
'begin',
|
||||||
|
' await(Run());',
|
||||||
|
'end;',
|
||||||
|
'begin',
|
||||||
|
' Fly(1);']);
|
||||||
|
SetExpectedPasResolverError('Wrong number of parameters specified for call to "function await(aType,TJSPromise):aType"',
|
||||||
|
nWrongNumberOfParametersForCallTo);
|
||||||
|
ConvertProgram;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestModule.TestAsync_AnonymousProc;
|
procedure TTestModule.TestAsync_AnonymousProc;
|
||||||
begin
|
begin
|
||||||
StartProgram(false);
|
StartProgram(false);
|
||||||
|
@ -3060,9 +3060,9 @@ End.
|
|||||||
Pas2js supports the JS operators async and await to simplify the use of Promise.
|
Pas2js supports the JS operators async and await to simplify the use of Promise.
|
||||||
The await operator corresponds to three intrinsic Pas2js functions:
|
The await operator corresponds to three intrinsic Pas2js functions:
|
||||||
<ul>
|
<ul>
|
||||||
<li><i>function await(AsyncFunctionWithResultT): T;</i> // implicit promise</li>
|
<li><i>function await(AsyncFunctionWithResultT()): T;</i> // implicit promise, the inner () can be omitted</li>
|
||||||
<li><i>function await(aType; p: TJSPromise): aType;</i> // explicit promise requires the resolved type</li>
|
<li><i>function await(aType; p: TJSPromise): aType;</i> // explicit promise requires the resolved type</li>
|
||||||
<li><i>function await(const Expr: T): T;</i> // implicit promise</li>
|
<li><i>function await(aType; j: jsvalue): aType;</i> // explicit promise requires the resolved type</li>
|
||||||
</ul>
|
</ul>
|
||||||
The await function can only be used inside a procedure with the async modifier.<br>
|
The await function can only be used inside a procedure with the async modifier.<br>
|
||||||
Example for the explicit promise:
|
Example for the explicit promise:
|
||||||
|
Loading…
Reference in New Issue
Block a user