From 621dcbeaf2118a9cb7622db19bb5d859e0e22f9d Mon Sep 17 00:00:00 2001 From: mattias Date: Sun, 6 Feb 2022 19:16:48 +0100 Subject: [PATCH] pastojs: library added rtl.run, moved exports behind rtl.run, fixed export unit symbols --- packages/fcl-js/src/jstree.pp | 2 +- packages/fcl-passrc/src/pasuseanalyzer.pas | 21 ++++++ packages/pastojs/src/fppas2js.pp | 33 ++++++++- packages/pastojs/tests/tcmodules.pas | 81 +++++++++++++++------- 4 files changed, 110 insertions(+), 27 deletions(-) diff --git a/packages/fcl-js/src/jstree.pp b/packages/fcl-js/src/jstree.pp index 4893778408..6f3fc11d1d 100644 --- a/packages/fcl-js/src/jstree.pp +++ b/packages/fcl-js/src/jstree.pp @@ -1014,7 +1014,7 @@ Type function GetNamedExports: TJSExportNameElements; Public Destructor Destroy; override; - Property IsDefault : Boolean Read FIsDefault Write FIsDefault; + Property IsDefault : Boolean Read FIsDefault Write FIsDefault; // write * Property Declaration : TJSElement Read FDeclaration Write FDeclaration; Property NameSpaceExport : TJSString Read FNameSpaceExport Write FNameSpaceExport; Property ModuleName : TJSString Read FModuleName Write FModuleName; diff --git a/packages/fcl-passrc/src/pasuseanalyzer.pas b/packages/fcl-passrc/src/pasuseanalyzer.pas index 641c8c88dc..df3a5be9b3 100644 --- a/packages/fcl-passrc/src/pasuseanalyzer.pas +++ b/packages/fcl-passrc/src/pasuseanalyzer.pas @@ -282,6 +282,7 @@ type procedure UseVariable(El: TPasVariable; Access: TResolvedRefAccess; UseFull: boolean); virtual; procedure UseResourcestring(El: TPasResString); virtual; + procedure UseExportSymbol(El: TPasExportSymbol); virtual; procedure UseArgument(El: TPasArgument; Access: TResolvedRefAccess); virtual; procedure UseResultElement(El: TPasResultElement; Access: TResolvedRefAccess); virtual; // create hints for a unit, program or library @@ -1467,6 +1468,8 @@ begin end else if C=TPasAttributes then // attributes are never used directly + else if C=TPasExportSymbol then + UseExportSymbol(TPasExportSymbol(Decl)) else RaiseNotSupported(20170306165213,Decl); end; @@ -2622,6 +2625,24 @@ begin UseExpr(El.Expr); end; +procedure TPasAnalyzer.UseExportSymbol(El: TPasExportSymbol); +var + Ref: TResolvedReference; + Decl: TPasElement; +begin + if not MarkElementAsUsed(El) then exit; + if El.CustomData is TResolvedReference then + begin + Ref:=TResolvedReference(El.CustomData); + Decl:=Ref.Declaration; + if Decl<>nil then + UseElement(Decl,Ref.Access,false); + end; + UseExpr(El.NameExpr); + UseExpr(El.ExportName); + UseExpr(El.ExportIndex); +end; + procedure TPasAnalyzer.UseArgument(El: TPasArgument; Access: TResolvedRefAccess ); var diff --git a/packages/pastojs/src/fppas2js.pp b/packages/pastojs/src/fppas2js.pp index 19858d5785..54a7d393b8 100644 --- a/packages/pastojs/src/fppas2js.pp +++ b/packages/pastojs/src/fppas2js.pp @@ -2097,6 +2097,7 @@ type Function CreateImplementationSection(El: TPasModule; IntfContext: TInterfaceSectionContext): TJSFunctionDeclarationStatement; virtual; Procedure CreateInitSection(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext); virtual; Procedure CreateExportsSection(El: TPasLibrary; Src: TJSSourceElements; AContext: TConvertContext); virtual; + Function AddLibraryRun(El: TPasLibrary; ModuleName: string; Src: TJSSourceElements; AContext: TConvertContext): TJSCallExpression; virtual; Procedure AddHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual; Procedure AddImplHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); virtual; function AddDelayedInits(El: TPasModule; Src: TJSSourceElements; AContext: TConvertContext): boolean; virtual; @@ -8207,7 +8208,10 @@ Library: }; }); - export1 = pas.unit1.func1; + rtl.run('library'); + var li = pas['library']; + export const func1 = pas.unit1.func1; + export const var1 = li.var1; Unit without implementation: rtl.module('', @@ -8337,7 +8341,6 @@ begin if Assigned(Lib.LibrarySection) then AddToSourceElements(Src,ConvertDeclarations(Lib.LibrarySection,IntfContext)); HasImplCode:=AddDelayedInits(Lib,Src,IntfContext); - CreateExportsSection(Lib,Src,IntfContext); CreateInitSection(Lib,Src,IntfContext); end else @@ -8387,6 +8390,14 @@ begin if (ModScope<>nil) and (coStoreImplJS in Options) then StoreImplJSLocals(ModScope,IntfContext); + + if El is TPasLibrary then + begin // library + Lib:=TPasLibrary(El); + AddLibraryRun(Lib,ModuleName,OuterSrc,AContext); + CreateExportsSection(Lib,OuterSrc,AContext); + end; + ok:=true; finally IntfContext.Free; @@ -18096,6 +18107,24 @@ begin end; end; +function TPasToJSConverter.AddLibraryRun(El: TPasLibrary; ModuleName: string; + Src: TJSSourceElements; AContext: TConvertContext): TJSCallExpression; +var + Call: TJSCallExpression; +begin + if AContext=nil then ; + + // add rtl.run('library'); + Call:=CreateCallExpression(El); + AddToSourceElements(Src,Call); + Call.Expr:=CreateMemberExpression([GetBIName(pbivnRTL),'run']); + + // add module name parameter + Call.AddArg(CreateLiteralString(El,ModuleName)); + + Result:=Call; +end; + procedure TPasToJSConverter.AddHeaderStatement(JS: TJSElement; PosEl: TPasElement; aContext: TConvertContext); var diff --git a/packages/pastojs/tests/tcmodules.pas b/packages/pastojs/tests/tcmodules.pas index bf4fe1d902..be8c9f1c1f 100644 --- a/packages/pastojs/tests/tcmodules.pas +++ b/packages/pastojs/tests/tcmodules.pas @@ -179,6 +179,7 @@ type function GetDottedIdentifier(El: TJSElement): string; procedure CheckSource(Msg,Statements: String; InitStatements: string = ''; ImplStatements: string = ''); virtual; + procedure CheckFullSource(Msg,ExpectedSrc: String); virtual; procedure CheckDiff(Msg, Expected, Actual: string); virtual; procedure CheckUnit(Filename, ExpectedSrc: string); virtual; procedure CheckHint(MsgType: TMessageType; MsgNumber: integer; @@ -919,9 +920,9 @@ type Procedure TestLibrary_Export_Index_Fail; Procedure TestLibrary_ExportVar; Procedure TestLibrary_ExportUnitFunc; - // todo: test fail on export overloaded function // ToDo: test delayed specialization init // ToDo: analyzer + // ToDo: shortrefoptimization end; function LinesToStr(Args: array of const): string; @@ -1989,7 +1990,7 @@ var InitFunction: TJSFunctionDeclarationStatement; InitAssign: TJSSimpleAssignStatement; InitName: String; - LastNode: TJSElement; + LastNode, FirstNode: TJSElement; Arg: TJSArrayLiteralElement; IsProg, IsLib: Boolean; begin @@ -2020,10 +2021,12 @@ begin {$ENDIF} // rtl.module(... - AssertEquals('jsmodule has one statement - the call',1,JSModule.Statements.Count); - AssertNotNull('register module call',JSModule.Statements.Nodes[0].Node); - AssertEquals('register module call',TJSCallExpression,JSModule.Statements.Nodes[0].Node.ClassType); - FJSRegModuleCall:=JSModule.Statements.Nodes[0].Node as TJSCallExpression; + if JSModule.Statements.Count<1 then + AssertEquals('jsmodule has at least one statement - the call',1,JSModule.Statements.Count); + FirstNode:=JSModule.Statements.Nodes[0].Node; + AssertNotNull('register module call',FirstNode); + AssertEquals('register module call',TJSCallExpression,FirstNode.ClassType); + FJSRegModuleCall:=FirstNode as TJSCallExpression; AssertNotNull('register module rtl.module expr',JSRegModuleCall.Expr); AssertNotNull('register module rtl.module args',JSRegModuleCall.Args); AssertEquals('rtl.module args',TJSArguments,JSRegModuleCall.Args.ClassType); @@ -2037,11 +2040,17 @@ begin ModuleNameExpr:=Arg.Expr as TJSLiteral; AssertEquals('module name param is string',ord(jstString),ord(ModuleNameExpr.Value.ValueType)); if IsProg then - AssertEquals('module name','program',String(ModuleNameExpr.Value.AsString)) + begin + AssertEquals('module name','program',String(ModuleNameExpr.Value.AsString)); + AssertEquals('jsmodule has one statement - the call',1,JSModule.Statements.Count); + end else if IsLib then AssertEquals('module name','library',String(ModuleNameExpr.Value.AsString)) else + begin AssertEquals('module name',Module.Name,String(ModuleNameExpr.Value.AsString)); + AssertEquals('jsmodule has one statement - the call',1,JSModule.Statements.Count); + end; // main uses section if JSModuleCallArgs.Elements.Count<2 then @@ -2187,6 +2196,14 @@ begin CheckDiff(Msg,ExpectedSrc,ActualSrc); end; +procedure TCustomTestModule.CheckFullSource(Msg, ExpectedSrc: String); +var + ActualSrc: String; +begin + ActualSrc:=JSToStr(JSModule); + CheckDiff(Msg,ExpectedSrc,ActualSrc); +end; + procedure TCustomTestModule.CheckDiff(Msg, Expected, Actual: string); // search diff, ignore changes in spaces var @@ -34134,10 +34151,14 @@ begin Add([ '']); ConvertLibrary; - CheckSource('TestLibrary_Empty', + CheckFullSource('TestLibrary_Empty', LinesToStr([ // statements - '']), - LinesToStr([ + 'rtl.module("library", [], function () {', + ' var $mod = this;', + ' $mod.$main = function () {', + ' };', + '});', + 'rtl.run("library");', ''])); CheckResolverUnexpectedHints(); end; @@ -34155,13 +34176,17 @@ begin ' test1.run name ''Test1Run'';', '']); ConvertLibrary; - CheckSource('TestLibrary_ExportFunc', + CheckFullSource('TestLibrary_ExportFunc', LinesToStr([ // statements - 'this.Run = function (w) {', - '};', - 'export { this.Run as Run, this.Run as Foo, this.Run as Test1Run };', - '']), - LinesToStr([ + 'rtl.module("library", [], function () {', + ' var $mod = this;', + ' this.Run = function (w) {', + ' };', + ' $mod.$main = function () {', + ' };', + '});', + 'rtl.run("library");', + 'export { pas.library.Run as Run, pas.library.Run as Foo, pas.library.Run as Test1Run };', ''])); CheckResolverUnexpectedHints(); end; @@ -34207,12 +34232,16 @@ begin ' Wing;', '']); ConvertLibrary; - CheckSource('TestLibrary_ExportVar', + CheckFullSource('TestLibrary_ExportVar', LinesToStr([ // statements - 'this.Wing = 0;', - 'export { this.Wing as Wing };', - '']), - LinesToStr([ + 'rtl.module("library", [], function () {', + ' var $mod = this;', + ' this.Wing = 0;', + ' $mod.$main = function () {', + ' };', + '});', + 'rtl.run("library");', + 'export { pas.library.Wing as Wing };', ''])); CheckResolverUnexpectedHints(); end; @@ -34244,11 +34273,15 @@ begin ' TAnt.Crawl;', '']); ConvertLibrary; - CheckSource('TestLibrary_ExportUnitFunc', + CheckFullSource('TestLibrary_ExportUnitFunc', LinesToStr([ // statements + 'rtl.module("library", ["system", "Unit1"], function () {', + ' var $mod = this;', + ' $mod.$main = function () {', + ' };', + '});', + 'rtl.run("library");', 'export { pas.Unit1.Fly as Fly, pas.Unit1.TAnt.Crawl as Crawl };', - '']), - LinesToStr([ ''])); CheckResolverUnexpectedHints(); end;