Browse Source

pastojs: fixed mem leak

git-svn-id: trunk@39462 -
Mattias Gaertner 7 years ago
parent
commit
acea898d9c

+ 105 - 93
packages/pastojs/src/fppas2js.pp

@@ -5137,117 +5137,123 @@ Var
   ModuleName, ModVarName: String;
   ModuleName, ModVarName: String;
   IntfContext: TSectionContext;
   IntfContext: TSectionContext;
   ImplVarSt: TJSVariableStatement;
   ImplVarSt: TJSVariableStatement;
-  HasImplUsesClause: Boolean;
+  HasImplUsesClause, ok: Boolean;
   UsesClause: TPasUsesClause;
   UsesClause: TPasUsesClause;
 begin
 begin
   Result:=Nil;
   Result:=Nil;
   OuterSrc:=TJSSourceElements(CreateElement(TJSSourceElements, El));
   OuterSrc:=TJSSourceElements(CreateElement(TJSSourceElements, El));
   Result:=OuterSrc;
   Result:=OuterSrc;
+  ok:=false;
+  try
+    // create 'rtl.module(...)'
+    RegModuleCall:=CreateCallExpression(El);
+    AddToSourceElements(OuterSrc,RegModuleCall);
+    RegModuleCall.Expr:=CreateMemberExpression([FBuiltInNames[pbivnRTL],'module']);
+    ArgArray := RegModuleCall.Args;
+    RegModuleCall.Args:=ArgArray;
+
+    // add unitname parameter: unitname
+    ModuleName:=TransformModuleName(El,false,AContext);
+    ArgArray.Elements.AddElement.Expr:=CreateLiteralString(El,ModuleName);
+
+    // add interface-uses-section parameter: [<interface uses1>,<uses2>, ...]
+    UsesSection:=nil;
+    if (El is TPasProgram) then
+      UsesSection:=TPasProgram(El).ProgramSection
+    else if (El is TPasLibrary) then
+      UsesSection:=TPasLibrary(El).LibrarySection
+    else
+      UsesSection:=El.InterfaceSection;
+    ArgArray.Elements.AddElement.Expr:=CreateUsesList(UsesSection,AContext);
 
 
-  // create 'rtl.module(...)'
-  RegModuleCall:=CreateCallExpression(El);
-  AddToSourceElements(OuterSrc,RegModuleCall);
-  RegModuleCall.Expr:=CreateMemberExpression([FBuiltInNames[pbivnRTL],'module']);
-  ArgArray := RegModuleCall.Args;
-  RegModuleCall.Args:=ArgArray;
-
-  // add unitname parameter: unitname
-  ModuleName:=TransformModuleName(El,false,AContext);
-  ArgArray.Elements.AddElement.Expr:=CreateLiteralString(El,ModuleName);
-
-  // add interface-uses-section parameter: [<interface uses1>,<uses2>, ...]
-  UsesSection:=nil;
-  if (El is TPasProgram) then
-    UsesSection:=TPasProgram(El).ProgramSection
-  else if (El is TPasLibrary) then
-    UsesSection:=TPasLibrary(El).LibrarySection
-  else
-    UsesSection:=El.InterfaceSection;
-  ArgArray.Elements.AddElement.Expr:=CreateUsesList(UsesSection,AContext);
+    // add interface parameter: function(){}
+    FunDecl:=CreateFunctionSt(El,true,true);
+    ArgArray.AddElement(FunDecl);
+    Src:=FunDecl.AFunction.Body.A as TJSSourceElements;
 
 
-  // add interface parameter: function(){}
-  FunDecl:=CreateFunctionSt(El,true,true);
-  ArgArray.AddElement(FunDecl);
-  Src:=FunDecl.AFunction.Body.A as TJSSourceElements;
+    if coUseStrict in Options then
+      // "use strict" must be the first statement in a function
+      AddToSourceElements(Src,CreateLiteralString(El,'use strict'));
 
 
-  if coUseStrict in Options then
-    // "use strict" must be the first statement in a function
-    AddToSourceElements(Src,CreateLiteralString(El,'use strict'));
+    ImplVarSt:=nil;
+    HasImplUsesClause:=false;
 
 
-  ImplVarSt:=nil;
-  HasImplUsesClause:=false;
+    IntfContext:=TSectionContext.Create(El,Src,AContext);
+    try
+      // add "var $mod = this;"
+      IntfContext.ThisPas:=El;
+      if El.CustomData is TPasModuleScope then
+        IntfContext.ScannerBoolSwitches:=TPasModuleScope(El.CustomData).BoolSwitches;
+      ModVarName:=FBuiltInNames[pbivnModule];
+      IntfContext.AddLocalVar(ModVarName,El);
+      AddToSourceElements(Src,CreateVarStatement(ModVarName,
+        CreatePrimitiveDotExpr('this',El),El));
+
+      if (El is TPasProgram) then
+        begin // program
+        if Assigned(TPasProgram(El).ProgramSection) then
+          AddToSourceElements(Src,ConvertDeclarations(TPasProgram(El).ProgramSection,IntfContext));
+        CreateInitSection(El,Src,IntfContext);
+        end
+      else if El is TPasLibrary then
+        begin // library
+        if Assigned(TPasLibrary(El).LibrarySection) then
+          AddToSourceElements(Src,ConvertDeclarations(TPasLibrary(El).LibrarySection,IntfContext));
+        CreateInitSection(El,Src,IntfContext);
+        end
+      else
+        begin // unit
+        if Assigned(El.ImplementationSection) then
+          begin
+          // add var $impl = $mod.$impl
+          ImplVarSt:=CreateVarStatement(FBuiltInNames[pbivnImplementation],
+            CreateMemberExpression([ModVarName,FBuiltInNames[pbivnImplementation]]),El);
+          AddToSourceElements(Src,ImplVarSt);
+          // register local var $impl
+          IntfContext.AddLocalVar(FBuiltInNames[pbivnImplementation],El.ImplementationSection);
+          end;
+        if Assigned(El.InterfaceSection) then
+          AddToSourceElements(Src,ConvertDeclarations(El.InterfaceSection,IntfContext));
+        CreateInitSection(El,Src,IntfContext);
 
 
-  IntfContext:=TSectionContext.Create(El,Src,AContext);
-  try
-    // add "var $mod = this;"
-    IntfContext.ThisPas:=El;
-    if El.CustomData is TPasModuleScope then
-      IntfContext.ScannerBoolSwitches:=TPasModuleScope(El.CustomData).BoolSwitches;
-    ModVarName:=FBuiltInNames[pbivnModule];
-    IntfContext.AddLocalVar(ModVarName,El);
-    AddToSourceElements(Src,CreateVarStatement(ModVarName,
-      CreatePrimitiveDotExpr('this',El),El));
+        // add optional implementation uses list: [<implementation uses1>,<uses2>, ...]
+        if Assigned(El.ImplementationSection) then
+          begin
+          UsesClause:=El.ImplementationSection.UsesClause;
+          if length(UsesClause)>0 then
+            begin
+            ArgArray.AddElement(CreateUsesList(El.ImplementationSection,AContext));
+            HasImplUsesClause:=true;
+            end;
+          end;
 
 
-    if (El is TPasProgram) then
-      begin // program
-      if Assigned(TPasProgram(El).ProgramSection) then
-        AddToSourceElements(Src,ConvertDeclarations(TPasProgram(El).ProgramSection,IntfContext));
-      CreateInitSection(El,Src,IntfContext);
-      end
-    else if El is TPasLibrary then
-      begin // library
-      if Assigned(TPasLibrary(El).LibrarySection) then
-        AddToSourceElements(Src,ConvertDeclarations(TPasLibrary(El).LibrarySection,IntfContext));
-      CreateInitSection(El,Src,IntfContext);
-      end
-    else
-      begin // unit
-      if Assigned(El.ImplementationSection) then
-        begin
-        // add var $impl = $mod.$impl
-        ImplVarSt:=CreateVarStatement(FBuiltInNames[pbivnImplementation],
-          CreateMemberExpression([ModVarName,FBuiltInNames[pbivnImplementation]]),El);
-        AddToSourceElements(Src,ImplVarSt);
-        // register local var $impl
-        IntfContext.AddLocalVar(FBuiltInNames[pbivnImplementation],El.ImplementationSection);
         end;
         end;
-      if Assigned(El.InterfaceSection) then
-        AddToSourceElements(Src,ConvertDeclarations(El.InterfaceSection,IntfContext));
-      CreateInitSection(El,Src,IntfContext);
+    finally
+      IntfContext.Free;
+    end;
 
 
-      // add optional implementation uses list: [<implementation uses1>,<uses2>, ...]
-      if Assigned(El.ImplementationSection) then
+    // add implementation function
+    if ImplVarSt<>nil then
+      begin
+      ImplFunc:=CreateImplementationSection(El,AContext);
+      if ImplFunc=nil then
         begin
         begin
-        UsesClause:=El.ImplementationSection.UsesClause;
-        if length(UsesClause)>0 then
-          begin
-          ArgArray.AddElement(CreateUsesList(El.ImplementationSection,AContext));
-          HasImplUsesClause:=true;
-          end;
+        // remove unneeded $impl from interface
+        RemoveFromSourceElements(Src,ImplVarSt);
+        end
+      else
+        begin
+        // add param
+        if not HasImplUsesClause then
+          ArgArray.AddElement(CreateLiteralNull(El));
+        ArgArray.AddElement(ImplFunc);
         end;
         end;
-
       end;
       end;
+    ok:=true;
   finally
   finally
-    IntfContext.Free;
+    if not ok then
+      FreeAndNil(Result);
   end;
   end;
-
-  // add implementation function
-  if ImplVarSt<>nil then
-    begin
-    ImplFunc:=CreateImplementationSection(El,AContext);
-    if ImplFunc=nil then
-      begin
-      // remove unneeded $impl from interface
-      RemoveFromSourceElements(Src,ImplVarSt);
-      end
-    else
-      begin
-      // add param
-      if not HasImplUsesClause then
-        ArgArray.AddElement(CreateLiteralNull(El));
-      ArgArray.AddElement(ImplFunc);
-      end;
-    end;
 end;
 end;
 
 
 function TPasToJSConverter.CreateElement(C: TJSElementClass; Src: TPasElement
 function TPasToJSConverter.CreateElement(C: TJSElementClass; Src: TPasElement
@@ -7653,7 +7659,10 @@ var
         begin
         begin
         AccessEl:=aResolver.GetPasPropertySetter(Prop);
         AccessEl:=aResolver.GetPasPropertySetter(Prop);
         if IsJSBracketAccessorAndConvert(Prop,AccessEl,AContext,true) then
         if IsJSBracketAccessorAndConvert(Prop,AccessEl,AContext,true) then
+          begin
+          FreeAndNil(Call);
           exit;
           exit;
+          end;
         AssignContext:=AContext.AccessContext as TAssignContext;
         AssignContext:=AContext.AccessContext as TAssignContext;
         AssignContext.PropertyEl:=Prop;
         AssignContext.PropertyEl:=Prop;
         AssignContext.Setter:=AccessEl;
         AssignContext.Setter:=AccessEl;
@@ -7663,7 +7672,10 @@ var
         begin
         begin
         AccessEl:=aResolver.GetPasPropertyGetter(Prop);
         AccessEl:=aResolver.GetPasPropertyGetter(Prop);
         if IsJSBracketAccessorAndConvert(Prop,AccessEl,AContext,true) then
         if IsJSBracketAccessorAndConvert(Prop,AccessEl,AContext,true) then
+          begin
+          FreeAndNil(Call);
           exit;
           exit;
+          end;
         end
         end
       else
       else
         RaiseNotSupported(El,AContext,20170213213317);
         RaiseNotSupported(El,AContext,20170213213317);

+ 9 - 1
packages/pastojs/tests/tcmodules.pas

@@ -1139,6 +1139,13 @@ begin
   {$IFDEF EnablePasTreeGlobalRefCount}
   {$IFDEF EnablePasTreeGlobalRefCount}
   FElementRefCountAtSetup:=TPasElement.GlobalRefCount;
   FElementRefCountAtSetup:=TPasElement.GlobalRefCount;
   {$ENDIF}
   {$ENDIF}
+
+  if FModules<>nil then
+    begin
+    writeln('TCustomTestModule.SetUp FModules<>nil');
+    Halt;
+    end;
+
   inherited SetUp;
   inherited SetUp;
   FSkipTests:=false;
   FSkipTests:=false;
   FSource:=TStringList.Create;
   FSource:=TStringList.Create;
@@ -1196,7 +1203,6 @@ begin
   FHintMsgs.Clear;
   FHintMsgs.Clear;
   FHintMsgsGood.Clear;
   FHintMsgsGood.Clear;
   FSkipTests:=false;
   FSkipTests:=false;
-  FJSModule:=nil;
   FJSRegModuleCall:=nil;
   FJSRegModuleCall:=nil;
   FJSModuleCallArgs:=nil;
   FJSModuleCallArgs:=nil;
   FJSImplentationUses:=nil;
   FJSImplentationUses:=nil;
@@ -1704,6 +1710,7 @@ begin
   writeln('CheckUnit '+Filename+' converting ...');
   writeln('CheckUnit '+Filename+' converting ...');
   {$ENDIF}
   {$ENDIF}
   aConverter:=CreateConverter;
   aConverter:=CreateConverter;
+  aJSModule:=nil;
   try
   try
     try
     try
       aJSModule:=aConverter.ConvertPasElement(aResolver.Module,aResolver) as TJSSourceElements;
       aJSModule:=aConverter.ConvertPasElement(aResolver.Module,aResolver) as TJSSourceElements;
@@ -1720,6 +1727,7 @@ begin
     {$ENDIF}
     {$ENDIF}
     CheckDiff('Converted unit: "'+ChangeFileExt(Filename,'.js')+'"',ExpectedSrc,ActualSrc);
     CheckDiff('Converted unit: "'+ChangeFileExt(Filename,'.js')+'"',ExpectedSrc,ActualSrc);
   finally
   finally
+    aJSModule.Free;
     aConverter.Free;
     aConverter.Free;
   end;
   end;
 end;
 end;

+ 1 - 0
packages/pastojs/tests/testpas2js.pp

@@ -17,6 +17,7 @@ program testpas2js;
 {$mode objfpc}{$H+}
 {$mode objfpc}{$H+}
 
 
 uses
 uses
+  //MemCheck,
   Classes, consoletestrunner, tcconverter, tcmodules, tcoptimizations, tcsrcmap,
   Classes, consoletestrunner, tcconverter, tcmodules, tcoptimizations, tcsrcmap,
   tcfiler, Pas2JsFiler, tcunitsearch, tcprecompile;
   tcfiler, Pas2JsFiler, tcunitsearch, tcprecompile;