Browse Source

pastojs: library added rtl.run, moved exports behind rtl.run, fixed export unit symbols

mattias 3 years ago
parent
commit
621dcbeaf2

+ 1 - 1
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;

+ 21 - 0
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

+ 31 - 2
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:
         <initialization>
         };
     });
-  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('<unitname>',
@@ -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

+ 57 - 24
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;