mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-04 17:10:20 +02:00
pastojs: added FindAvailableLocalName
git-svn-id: trunk@38454 -
This commit is contained in:
parent
5c6eb1b9a3
commit
27508cdd23
@ -1228,7 +1228,7 @@ type
|
||||
|
||||
TPasToJSConverter = Class(TObject)
|
||||
private
|
||||
// inline at top, only functions declared after the inline implementation actually use it
|
||||
// inline at ttop, because fpc 3.1 requires inline implementation in front of use
|
||||
function GetUseEnumNumbers: boolean; inline;
|
||||
function GetUseLowerCase: boolean; inline;
|
||||
function GetUseSwitchStatement: boolean; inline;
|
||||
@ -1289,11 +1289,13 @@ type
|
||||
Function IsPreservedWord(const aName: string): boolean; virtual;
|
||||
Function GetTypeInfoName(El: TPasType; AContext: TConvertContext;
|
||||
ErrorEl: TPasElement): String; virtual;
|
||||
// Never create an element manually, always use the below functions
|
||||
// utility functions for creating stuff
|
||||
Function IsElementUsed(El: TPasElement): boolean; virtual;
|
||||
Function IsSystemUnit(aModule: TPasModule): boolean; virtual;
|
||||
Function HasTypeInfo(El: TPasType; AContext: TConvertContext): boolean; virtual;
|
||||
Function IsClassRTTICreatedBefore(aClass: TPasClassType; Before: TPasElement; AConText: TConvertContext): boolean;
|
||||
Procedure FindAvailableLocalName(var aName: string; JSExpr: TJSElement);
|
||||
// Never create an element manually, always use the below functions
|
||||
Function CreateElement(C: TJSElementClass; Src: TPasElement): TJSElement; virtual;
|
||||
Function CreateFreeOrNewInstanceExpr(Ref: TResolvedReference;
|
||||
AContext : TConvertContext): TJSCallExpression; virtual;
|
||||
@ -1375,7 +1377,7 @@ type
|
||||
Function CreateCallRTLFreeLoc(Setter, Getter: TJSElement; Src: TPasElement): TJSElement; virtual;
|
||||
Function CreatePropertyGet(Prop: TPasProperty; Ref: TResolvedReference;
|
||||
AContext: TConvertContext; PosEl: TPasElement): TJSElement; virtual;
|
||||
Function StorePrecompiledJS(El: TJSElement): string; virtual;
|
||||
Function CreatePrecompiledJS(El: TJSElement): string; virtual;
|
||||
// Statements
|
||||
Function ConvertImplBlockElements(El: TPasImplBlock; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; virtual;
|
||||
Function ConvertBeginEndStatement(El: TPasImplBeginBlock; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; virtual;
|
||||
@ -1545,7 +1547,6 @@ const
|
||||
TempRefObjGetterName = 'get';
|
||||
TempRefObjSetterName = 'set';
|
||||
TempRefObjSetterArgName = 'v';
|
||||
TempRefObjSetterArgNameAlt = 'p';
|
||||
|
||||
function CodePointToJSString(u: longword): TJSString;
|
||||
begin
|
||||
@ -9701,7 +9702,7 @@ begin
|
||||
if (coStoreImplJS in Options) and (AContext.Resolver<>nil) then
|
||||
begin
|
||||
if AContext.Resolver.GetTopLvlProc(El)=El then
|
||||
ImplProcScope.BodyJS:=StorePrecompiledJS(Result);
|
||||
ImplProcScope.BodyJS:=CreatePrecompiledJS(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -9801,7 +9802,7 @@ begin
|
||||
end;
|
||||
|
||||
if (coStoreImplJS in Options) and (AContext.Resolver<>nil) then
|
||||
Scope.JS:=StorePrecompiledJS(Result);
|
||||
Scope.JS:=CreatePrecompiledJS(Result);
|
||||
end;
|
||||
|
||||
function TPasToJSConverter.ConvertFinalizationSection(El: TFinalizationSection;
|
||||
@ -11111,7 +11112,7 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TPasToJSConverter.StorePrecompiledJS(El: TJSElement): string;
|
||||
function TPasToJSConverter.CreatePrecompiledJS(El: TJSElement): string;
|
||||
var
|
||||
aWriter: TBufferWriter;
|
||||
aJSWriter: TJSWriter;
|
||||
@ -12303,6 +12304,162 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TPasToJSConverter.FindAvailableLocalName(var aName: string;
|
||||
JSExpr: TJSElement);
|
||||
var
|
||||
StartJSName, JSName: TJSString;
|
||||
n: integer;
|
||||
Changed: boolean;
|
||||
|
||||
procedure Next;
|
||||
var
|
||||
ch: WideChar;
|
||||
begin
|
||||
Changed:=true;
|
||||
// name clash -> change JSName
|
||||
if (n=0) and (length(JSName)=1) then
|
||||
begin
|
||||
// single letter -> choose next single letter
|
||||
ch:=JSName[1];
|
||||
case ch of
|
||||
'a'..'x': JSName:=succ(ch);
|
||||
'z': JSName:='a';
|
||||
end;
|
||||
if JSName=StartJSName then
|
||||
begin
|
||||
n:=1;
|
||||
JSName:=StartJSName+TJSString(IntToStr(n));
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
inc(n);
|
||||
JSName:=StartJSName+TJSString(IntToStr(n));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure Find(El: TJSElement);
|
||||
var
|
||||
C: TClass;
|
||||
Call: TJSCallExpression;
|
||||
i: Integer;
|
||||
begin
|
||||
if El=nil then exit;
|
||||
C:=El.ClassType;
|
||||
if C=TJSPrimaryExpressionIdent then
|
||||
begin
|
||||
if TJSPrimaryExpressionIdent(El).Name=JSName then
|
||||
Next;
|
||||
end
|
||||
else if C.InheritsFrom(TJSMemberExpression) then
|
||||
begin
|
||||
Find(TJSMemberExpression(El).MExpr);
|
||||
if C=TJSBracketMemberExpression then
|
||||
Find(TJSBracketMemberExpression(El).Name)
|
||||
else if C=TJSNewMemberExpression then
|
||||
with TJSNewMemberExpression(El).Args.Elements do
|
||||
for i:=0 to Count-1 do
|
||||
Find(Elements[i].Expr)
|
||||
end
|
||||
else if C=TJSCallExpression then
|
||||
begin
|
||||
Call:=TJSCallExpression(El);
|
||||
Find(Call.Expr);
|
||||
if Call.Args<>nil then
|
||||
with Call.Args.Elements do
|
||||
for i:=0 to Count-1 do
|
||||
Find(Elements[i].Expr);
|
||||
end
|
||||
else if C.InheritsFrom(TJSUnary) then
|
||||
Find(TJSUnary(El).A)
|
||||
else if C.InheritsFrom(TJSBinary) then
|
||||
begin
|
||||
Find(TJSBinary(El).A);
|
||||
Find(TJSBinary(El).B);
|
||||
end
|
||||
else if C=TJSArrayLiteral then
|
||||
begin
|
||||
with TJSArrayLiteral(El).Elements do
|
||||
for i:=0 to Count-1 do
|
||||
Find(Elements[i].Expr);
|
||||
end
|
||||
else if C=TJSConditionalExpression then
|
||||
begin
|
||||
Find(TJSConditionalExpression(El).A);
|
||||
Find(TJSConditionalExpression(El).B);
|
||||
Find(TJSConditionalExpression(El).C);
|
||||
end
|
||||
else if C.InheritsFrom(TJSAssignStatement) then
|
||||
begin
|
||||
Find(TJSAssignStatement(El).LHS);
|
||||
Find(TJSAssignStatement(El).Expr);
|
||||
end
|
||||
else if C=TJSVarDeclaration then
|
||||
Find(TJSVarDeclaration(El).Init)
|
||||
else if C=TJSObjectLiteral then
|
||||
begin
|
||||
with TJSObjectLiteral(El).Elements do
|
||||
for i:=0 to Count-1 do
|
||||
Find(Elements[i].Expr);
|
||||
end
|
||||
else if C=TJSIfStatement then
|
||||
begin
|
||||
Find(TJSIfStatement(El).Cond);
|
||||
Find(TJSIfStatement(El).BTrue);
|
||||
Find(TJSIfStatement(El).BFalse);
|
||||
end
|
||||
else if C.InheritsFrom(TJSBodyStatement) then
|
||||
begin
|
||||
Find(TJSBodyStatement(El).Body);
|
||||
if C.InheritsFrom(TJSCondLoopStatement) then
|
||||
begin
|
||||
Find(TJSCondLoopStatement(El).Cond);
|
||||
if C=TJSForStatement then
|
||||
begin
|
||||
Find(TJSForStatement(El).Init);
|
||||
Find(TJSForStatement(El).Incr);
|
||||
end;
|
||||
end
|
||||
else if C=TJSForInStatement then
|
||||
begin
|
||||
Find(TJSForInStatement(El).LHS);
|
||||
Find(TJSForInStatement(El).List);
|
||||
end;
|
||||
end
|
||||
else if C=TJSSwitchStatement then
|
||||
begin
|
||||
Find(TJSSwitchStatement(El).Cond);
|
||||
with TJSSwitchStatement(El).Cases do
|
||||
for i:=0 to Count-1 do
|
||||
with Cases[i] do
|
||||
begin
|
||||
Find(Expr);
|
||||
Find(Body);
|
||||
end;
|
||||
if TJSSwitchStatement(El).TheDefault<>nil then
|
||||
with TJSSwitchStatement(El).TheDefault do
|
||||
begin
|
||||
Find(Expr);
|
||||
Find(Body);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
if JSExpr=nil then exit;
|
||||
StartJSName:=TJSString(aName);
|
||||
JSName:=StartJSName;
|
||||
n:=0;
|
||||
Changed:=false;
|
||||
Find(JSExpr);
|
||||
if not Changed then exit;
|
||||
repeat
|
||||
Changed:=false;
|
||||
Find(JSExpr);
|
||||
until not changed;
|
||||
aName:=UTF8Encode(JSName);
|
||||
end;
|
||||
|
||||
function TPasToJSConverter.CreateUnary(Members: array of string; E: TJSElement): TJSUnary;
|
||||
var
|
||||
unary: TJSUnary;
|
||||
@ -13407,7 +13564,7 @@ var
|
||||
GetPath, SetPath: String;
|
||||
BracketExpr: TJSBracketMemberExpression;
|
||||
DotExpr: TJSDotMemberExpression;
|
||||
SetterArgName: Char;
|
||||
SetterArgName: String;
|
||||
begin
|
||||
// pass reference -> create a temporary JS object with a FullGetter and setter
|
||||
Obj:=nil;
|
||||
@ -13575,9 +13732,7 @@ begin
|
||||
// create SetExpr = v;
|
||||
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
|
||||
AssignSt.LHS:=SetExpr;
|
||||
if (SetExpr is TJSPrimaryExpressionIdent)
|
||||
and (TJSPrimaryExpressionIdent(SetExpr).Name=TJSString(SetterArgName)) then
|
||||
SetterArgName:=TempRefObjSetterArgNameAlt;
|
||||
FindAvailableLocalName(SetterArgName,SetExpr);
|
||||
AssignSt.Expr:=CreatePrimitiveDotExpr(SetterArgName,El);
|
||||
SetExpr:=AssignSt;
|
||||
end
|
||||
@ -13800,7 +13955,7 @@ begin
|
||||
if Proc<>nil then
|
||||
begin
|
||||
ProcScope:=TPas2JSProcedureScope(Proc.CustomData);
|
||||
ProcScope.AddGlobalJS(StorePrecompiledJS(V));
|
||||
ProcScope.AddGlobalJS(CreatePrecompiledJS(V));
|
||||
end;
|
||||
end;
|
||||
end
|
||||
|
@ -2987,8 +2987,10 @@ begin
|
||||
' i:=i+2;',
|
||||
'end;',
|
||||
'procedure DoIt(v: longint);',
|
||||
'var p: array of longint;',
|
||||
'begin',
|
||||
' Inc2(v);',
|
||||
' Inc2(p[v]);',
|
||||
'end;',
|
||||
'begin']);
|
||||
ConvertProgram;
|
||||
@ -2998,11 +3000,22 @@ begin
|
||||
' i.set(i.get()+2);',
|
||||
'};',
|
||||
'this.DoIt = function (v) {',
|
||||
' var p = [];',
|
||||
' $mod.Inc2({get: function () {',
|
||||
' return v;',
|
||||
' }, set: function (p) {',
|
||||
' v = p;',
|
||||
' }, set: function (w) {',
|
||||
' v = w;',
|
||||
' }});',
|
||||
' $mod.Inc2({',
|
||||
' a: v,',
|
||||
' p: p,',
|
||||
' get: function () {',
|
||||
' return this.p[this.a];',
|
||||
' },',
|
||||
' set: function (v) {',
|
||||
' this.p[this.a] = v;',
|
||||
' }',
|
||||
' });',
|
||||
'};',
|
||||
'']),
|
||||
LinesToStr([
|
||||
|
Loading…
Reference in New Issue
Block a user