From acea898d9cfe84227524a989ccdbe22a3f510403 Mon Sep 17 00:00:00 2001 From: Mattias Gaertner Date: Tue, 17 Jul 2018 07:10:15 +0000 Subject: [PATCH] pastojs: fixed mem leak git-svn-id: trunk@39462 - --- packages/pastojs/src/fppas2js.pp | 206 ++++++++++++++------------- packages/pastojs/tests/tcmodules.pas | 10 +- packages/pastojs/tests/testpas2js.pp | 1 + 3 files changed, 119 insertions(+), 98 deletions(-) diff --git a/packages/pastojs/src/fppas2js.pp b/packages/pastojs/src/fppas2js.pp index 7aab0ace91..02e5f3a8ea 100644 --- a/packages/pastojs/src/fppas2js.pp +++ b/packages/pastojs/src/fppas2js.pp @@ -5137,117 +5137,123 @@ Var ModuleName, ModVarName: String; IntfContext: TSectionContext; ImplVarSt: TJSVariableStatement; - HasImplUsesClause: Boolean; + HasImplUsesClause, ok: Boolean; UsesClause: TPasUsesClause; begin Result:=Nil; OuterSrc:=TJSSourceElements(CreateElement(TJSSourceElements, El)); Result:=OuterSrc; - - // 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: [,, ...] - 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; - - 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; - - IntfContext:=TSectionContext.Create(El,Src,AContext); + ok:=false; 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)); + // 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: [,, ...] + UsesSection:=nil; 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 + UsesSection:=TPasProgram(El).ProgramSection + else if (El is TPasLibrary) then + UsesSection:=TPasLibrary(El).LibrarySection 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); + UsesSection:=El.InterfaceSection; + ArgArray.Elements.AddElement.Expr:=CreateUsesList(UsesSection,AContext); - // add optional implementation uses list: [,, ...] - if Assigned(El.ImplementationSection) then - begin - UsesClause:=El.ImplementationSection.UsesClause; - if length(UsesClause)>0 then + // 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')); + + 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 - ArgArray.AddElement(CreateUsesList(El.ImplementationSection,AContext)); - HasImplUsesClause:=true; + // 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); + + // add optional implementation uses list: [,, ...] + 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; + end; - - end; - finally - IntfContext.Free; - 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; + finally + IntfContext.Free; 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; + ok:=true; + finally + if not ok then + FreeAndNil(Result); + end; end; function TPasToJSConverter.CreateElement(C: TJSElementClass; Src: TPasElement @@ -7653,7 +7659,10 @@ var begin AccessEl:=aResolver.GetPasPropertySetter(Prop); if IsJSBracketAccessorAndConvert(Prop,AccessEl,AContext,true) then + begin + FreeAndNil(Call); exit; + end; AssignContext:=AContext.AccessContext as TAssignContext; AssignContext.PropertyEl:=Prop; AssignContext.Setter:=AccessEl; @@ -7663,7 +7672,10 @@ var begin AccessEl:=aResolver.GetPasPropertyGetter(Prop); if IsJSBracketAccessorAndConvert(Prop,AccessEl,AContext,true) then + begin + FreeAndNil(Call); exit; + end; end else RaiseNotSupported(El,AContext,20170213213317); diff --git a/packages/pastojs/tests/tcmodules.pas b/packages/pastojs/tests/tcmodules.pas index b9ac1a167f..2ff1c265a9 100644 --- a/packages/pastojs/tests/tcmodules.pas +++ b/packages/pastojs/tests/tcmodules.pas @@ -1139,6 +1139,13 @@ begin {$IFDEF EnablePasTreeGlobalRefCount} FElementRefCountAtSetup:=TPasElement.GlobalRefCount; {$ENDIF} + + if FModules<>nil then + begin + writeln('TCustomTestModule.SetUp FModules<>nil'); + Halt; + end; + inherited SetUp; FSkipTests:=false; FSource:=TStringList.Create; @@ -1196,7 +1203,6 @@ begin FHintMsgs.Clear; FHintMsgsGood.Clear; FSkipTests:=false; - FJSModule:=nil; FJSRegModuleCall:=nil; FJSModuleCallArgs:=nil; FJSImplentationUses:=nil; @@ -1704,6 +1710,7 @@ begin writeln('CheckUnit '+Filename+' converting ...'); {$ENDIF} aConverter:=CreateConverter; + aJSModule:=nil; try try aJSModule:=aConverter.ConvertPasElement(aResolver.Module,aResolver) as TJSSourceElements; @@ -1720,6 +1727,7 @@ begin {$ENDIF} CheckDiff('Converted unit: "'+ChangeFileExt(Filename,'.js')+'"',ExpectedSrc,ActualSrc); finally + aJSModule.Free; aConverter.Free; end; end; diff --git a/packages/pastojs/tests/testpas2js.pp b/packages/pastojs/tests/testpas2js.pp index 23c8028dce..77f7be7e7d 100644 --- a/packages/pastojs/tests/testpas2js.pp +++ b/packages/pastojs/tests/testpas2js.pp @@ -17,6 +17,7 @@ program testpas2js; {$mode objfpc}{$H+} uses + //MemCheck, Classes, consoletestrunner, tcconverter, tcmodules, tcoptimizations, tcsrcmap, tcfiler, Pas2JsFiler, tcunitsearch, tcprecompile;