pastojs: srcmap: keep position at curly brackets, fixed bracket accessor

git-svn-id: trunk@37264 -
This commit is contained in:
Mattias Gaertner 2017-09-20 09:13:01 +00:00
parent 4b4e40c98e
commit 77b1cfcd0d
4 changed files with 131 additions and 154 deletions

View File

@ -51,7 +51,7 @@ Works:
ToDo: ToDo:
- arrays - arrays
- [], [a..b], [a,b], + - [], [a..b], multi dim [a,b], concat with +
- array of record - array of record
- array of string - array of string
- error on: array[1..2] of longint = (1,2,3); - error on: array[1..2] of longint = (1,2,3);

View File

@ -1132,7 +1132,7 @@ type
FPreservedWords: TJSReservedWordList; // sorted with CompareStr FPreservedWords: TJSReservedWordList; // sorted with CompareStr
FTargetPlatform: TPasToJsPlatform; FTargetPlatform: TPasToJsPlatform;
FTargetProcessor: TPasToJsProcessor; FTargetProcessor: TPasToJsProcessor;
Function CreatePrimitiveDotExpr(AName: string; Src: TPasElement = nil): TJSElement; Function CreatePrimitiveDotExpr(AName: string; Src: TPasElement): TJSElement;
Function CreateSubDeclNameExpr(El: TPasElement; const Name: string; Function CreateSubDeclNameExpr(El: TPasElement; const Name: string;
AContext: TConvertContext; PosEl: TPasElement = nil): TJSElement; AContext: TConvertContext; PosEl: TPasElement = nil): TJSElement;
Function CreateIdentifierExpr(El: TPasElement; AContext: TConvertContext): TJSElement; Function CreateIdentifierExpr(El: TPasElement; AContext: TConvertContext): TJSElement;
@ -3595,7 +3595,7 @@ begin
ModVarName:=FBuiltInNames[pbivnModule]; ModVarName:=FBuiltInNames[pbivnModule];
IntfContext.AddLocalVar(ModVarName,El); IntfContext.AddLocalVar(ModVarName,El);
AddToSourceElements(Src,CreateVarStatement(ModVarName, AddToSourceElements(Src,CreateVarStatement(ModVarName,
CreatePrimitiveDotExpr('this'),El)); CreatePrimitiveDotExpr('this',El),El));
if (El is TPasProgram) then if (El is TPasProgram) then
begin // program begin // program
@ -3710,7 +3710,7 @@ begin
else else
FunName:=FBuiltInNames[pbifnClassInstanceFree]; FunName:=FBuiltInNames[pbifnClassInstanceFree];
FunName:=CreateReferencePath(Proc,AContext,rpkPathWithDot,false,Ref)+FunName; FunName:=CreateReferencePath(Proc,AContext,rpkPathWithDot,false,Ref)+FunName;
C.Expr:=CreatePrimitiveDotExpr(FunName); C.Expr:=CreatePrimitiveDotExpr(FunName,Ref.Element);
ArgElems:=C.Args.Elements; ArgElems:=C.Args.Elements;
// parameter: "funcname" // parameter: "funcname"
ArgEx := CreateLiteralString(Ref.Element,TransformVariableName(Proc,AContext)); ArgEx := CreateLiteralString(Ref.Element,TransformVariableName(Proc,AContext));
@ -4099,12 +4099,13 @@ begin
begin begin
// "A as B" // "A as B"
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
if (RightResolved.TypeEl is TPasClassType) and TPasClassType(RightResolved.TypeEl).IsExternal then if (RightResolved.TypeEl is TPasClassType)
and TPasClassType(RightResolved.TypeEl).IsExternal then
// B is external class -> "rtl.asExt(A,B)" // B is external class -> "rtl.asExt(A,B)"
Call.Expr:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTL]+'.'+FBuiltInNames[pbifnAsExt]) Call.Expr:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTL]+'.'+FBuiltInNames[pbifnAsExt],El)
else else
// otherwise -> "rtl.as(A,B)" // otherwise -> "rtl.as(A,B)"
Call.Expr:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTL]+'.'+FBuiltInNames[pbifnAs]); Call.Expr:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTL]+'.'+FBuiltInNames[pbifnAs],El);
Call.AddArg(A); Call.AddArg(A);
Call.AddArg(B); Call.AddArg(B);
Result:=Call; Result:=Call;
@ -4137,7 +4138,7 @@ begin
eopPower: eopPower:
begin begin
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
Call.Expr:=CreatePrimitiveDotExpr('Math.pow'); Call.Expr:=CreatePrimitiveDotExpr('Math.pow',El);
Call.AddArg(A); Call.AddArg(A);
Call.AddArg(B); Call.AddArg(B);
Result:=Call; Result:=Call;
@ -4158,7 +4159,7 @@ begin
// convert "a div b" to "Math.floor(a/b)" // convert "a div b" to "Math.floor(a/b)"
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
Call.AddArg(R); Call.AddArg(R);
Call.Expr:=CreatePrimitiveDotExpr('Math.floor'); Call.Expr:=CreatePrimitiveDotExpr('Math.floor',El);
Result:=Call; Result:=Call;
end; end;
end; end;
@ -4302,7 +4303,7 @@ begin
begin begin
// convert "recordA = recordB" to "recordA.$equal(recordB)" // convert "recordA = recordB" to "recordA.$equal(recordB)"
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
Call.Expr:=CreateDotExpression(El,A,CreatePrimitiveDotExpr(FBuiltInNames[pbifnRecordEqual])); Call.Expr:=CreateDotExpression(El,A,CreatePrimitiveDotExpr(FBuiltInNames[pbifnRecordEqual],El));
A:=nil; A:=nil;
Call.AddArg(B); Call.AddArg(B);
B:=nil; B:=nil;
@ -4658,7 +4659,7 @@ begin
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
Call.Expr:=CreateDotExpression(El, Call.Expr:=CreateDotExpression(El,
CreateIdentifierExpr(Arg.Name,Arg,AContext), CreateIdentifierExpr(Arg.Name,Arg,AContext),
CreatePrimitiveDotExpr(TempRefObjGetterName)); CreatePrimitiveDotExpr(TempRefObjGetterName,El));
Result:=Call; Result:=Call;
exit; exit;
end; end;
@ -4672,7 +4673,7 @@ begin
AssignContext.Call:=Call; AssignContext.Call:=Call;
Call.Expr:=CreateDotExpression(El, Call.Expr:=CreateDotExpression(El,
CreateIdentifierExpr(Arg.Name,Arg,AContext), CreateIdentifierExpr(Arg.Name,Arg,AContext),
CreatePrimitiveDotExpr(TempRefObjSetterName)); CreatePrimitiveDotExpr(TempRefObjSetterName,El));
Call.AddArg(AssignContext.RightSide); Call.AddArg(AssignContext.RightSide);
AssignContext.RightSide:=nil; AssignContext.RightSide:=nil;
Result:=Call; Result:=Call;
@ -4836,11 +4837,11 @@ function TPasToJSConverter.ConvertInheritedExpression(El: TInheritedExpr;
Call:=nil; Call:=nil;
try try
Call:=CreateCallExpression(ParentEl); Call:=CreateCallExpression(ParentEl);
Call.Expr:=CreatePrimitiveDotExpr(FunName); Call.Expr:=CreatePrimitiveDotExpr(FunName,ParentEl);
Call.AddArg(CreatePrimitiveDotExpr(SelfName)); Call.AddArg(CreatePrimitiveDotExpr(SelfName,ParentEl));
if Apply then if Apply then
// "inherited;" -> pass the arguments // "inherited;" -> pass the arguments
Call.AddArg(CreatePrimitiveDotExpr('arguments')) Call.AddArg(CreatePrimitiveDotExpr('arguments',ParentEl))
else else
// "inherited Name(...)" -> pass the user arguments // "inherited Name(...)" -> pass the user arguments
CreateProcedureCall(Call,ParamsExpr,AncestorProc.ProcType,AContext); CreateProcedureCall(Call,ParamsExpr,AncestorProc.ProcType,AContext);
@ -5166,7 +5167,8 @@ var
begin begin
// convert char to int -> Arg.charCodeAt(0) // convert char to int -> Arg.charCodeAt(0)
Call:=CreateCallExpression(Param); Call:=CreateCallExpression(Param);
Call.Expr:=CreateDotExpression(Param,Arg,CreatePrimitiveDotExpr('charCodeAt')); Call.Expr:=CreateDotExpression(Param,Arg,
CreatePrimitiveDotExpr('charCodeAt',Param));
Arg:=Call; Arg:=Call;
Call.Args.AddElement(CreateLiteralNumber(Param,0)); Call.Args.AddElement(CreateLiteralNumber(Param,0));
end; end;
@ -5280,7 +5282,7 @@ var
if Prop.Args.Count<>1 then if Prop.Args.Count<>1 then
RaiseInconsistency(20170403003753); RaiseInconsistency(20170403003753);
// bracket accessor of external class -> create PathEl[param] // bracket accessor of external class -> create PathEl[param]
Bracket:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression,Prop)); Bracket:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression,El.Params[0]));
try try
PathEl:=El.Value; PathEl:=El.Value;
if ChompPropName then if ChompPropName then
@ -5293,7 +5295,7 @@ var
Ref:=TResolvedReference(PathEl.CustomData); Ref:=TResolvedReference(PathEl.CustomData);
Path:=CreateReferencePath(Prop,AContext,rpkPath,false,Ref); Path:=CreateReferencePath(Prop,AContext,rpkPath,false,Ref);
if Path<>'' then if Path<>'' then
Bracket.MExpr:=CreatePrimitiveDotExpr(Path); Bracket.MExpr:=CreatePrimitiveDotExpr(Path,PathEl);
PathEl:=nil; PathEl:=nil;
end end
else if (PathEl is TBinaryExpr) else if (PathEl is TBinaryExpr)
@ -5819,7 +5821,7 @@ begin
else else
// use external class name // use external class name
ExtName:=(Proc.Parent as TPasClassType).ExternalName; ExtName:=(Proc.Parent as TPasClassType).ExternalName;
ExtNameEl:=CreatePrimitiveDotExpr(ExtName); ExtNameEl:=CreatePrimitiveDotExpr(ExtName,Ref.Element);
end; end;
if CompareText(Proc.Name,'new')=0 then if CompareText(Proc.Name,'new')=0 then
@ -6308,7 +6310,7 @@ begin
// default: Param.length // default: Param.length
Arg:=ConvertElement(Param,AContext); Arg:=ConvertElement(Param,AContext);
Result:=CreateDotExpression(El,Arg,CreatePrimitiveDotExpr('length')); Result:=CreateDotExpression(El,Arg,CreatePrimitiveDotExpr('length',El));
end; end;
function TPasToJSConverter.ConvertBuiltIn_SetLength(El: TParamsExpr; function TPasToJSConverter.ConvertBuiltIn_SetLength(El: TParamsExpr;
@ -6466,7 +6468,7 @@ begin
ProcEl:=ProcEl.Parent; ProcEl:=ProcEl.Parent;
if ProcEl is TPasFunction then if ProcEl is TPasFunction then
// in a function, "return result;" // in a function, "return result;"
TJSReturnStatement(Result).Expr:=CreatePrimitiveDotExpr(ResolverResultVar) TJSReturnStatement(Result).Expr:=CreatePrimitiveDotExpr(ResolverResultVar,El)
else else
; // in a procedure, "return;" which means "return undefined;" ; // in a procedure, "return;" which means "return undefined;"
end; end;
@ -6522,7 +6524,7 @@ begin
// create "ref.set" // create "ref.set"
Call.Expr:=CreateDotExpression(El, Call.Expr:=CreateDotExpression(El,
CreateIdentifierExpr(ExprResolved.IdentEl,AContext), CreateIdentifierExpr(ExprResolved.IdentEl,AContext),
CreatePrimitiveDotExpr(TempRefObjSetterName)); CreatePrimitiveDotExpr(TempRefObjSetterName,El));
// create "+" // create "+"
if IsInc then if IsInc then
AddJS:=TJSAdditiveExpressionPlus(CreateElement(TJSAdditiveExpressionPlus,El)) AddJS:=TJSAdditiveExpressionPlus(CreateElement(TJSAdditiveExpressionPlus,El))
@ -6533,7 +6535,7 @@ begin
AddJS.A:=TJSCallExpression(CreateElement(TJSCallExpression,El)); AddJS.A:=TJSCallExpression(CreateElement(TJSCallExpression,El));
TJSCallExpression(AddJS.A).Expr:=CreateDotExpression(El, TJSCallExpression(AddJS.A).Expr:=CreateDotExpression(El,
CreateIdentifierExpr(ExprResolved.IdentEl,AContext), CreateIdentifierExpr(ExprResolved.IdentEl,AContext),
CreatePrimitiveDotExpr(TempRefObjGetterName)); CreatePrimitiveDotExpr(TempRefObjGetterName,El));
// add "b" // add "b"
AddJS.B:=ValueJS; AddJS.B:=ValueJS;
ValueJS:=nil; ValueJS:=nil;
@ -6687,7 +6689,8 @@ begin
Call:=nil; Call:=nil;
try try
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
Call.Expr:=CreateDotExpression(El,SubParamJS,CreatePrimitiveDotExpr('charCodeAt')); Call.Expr:=CreateDotExpression(El,SubParamJS,
CreatePrimitiveDotExpr('charCodeAt',El));
Minus:=TJSAdditiveExpressionMinus(CreateElement(TJSAdditiveExpressionMinus,Param)); Minus:=TJSAdditiveExpressionMinus(CreateElement(TJSAdditiveExpressionMinus,Param));
Call.AddArg(Minus); Call.AddArg(Minus);
if length(SubParams.Params)<>1 then if length(SubParams.Params)<>1 then
@ -6707,7 +6710,7 @@ begin
Result:=ConvertElement(Param,AContext); Result:=ConvertElement(Param,AContext);
// Note: convert Param first, as it might raise an exception // Note: convert Param first, as it might raise an exception
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
Call.Expr:=CreateDotExpression(El,Result,CreatePrimitiveDotExpr('charCodeAt')); Call.Expr:=CreateDotExpression(El,Result,CreatePrimitiveDotExpr('charCodeAt',El));
Result:=Call; Result:=Call;
exit; exit;
end end
@ -7083,7 +7086,7 @@ begin
// precision -> rtl El.toFixed(precision); // precision -> rtl El.toFixed(precision);
NeedStrLit:=false; NeedStrLit:=false;
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
Call.Expr:=CreateDotExpression(El,Add,CreatePrimitiveDotExpr('toFixed')); Call.Expr:=CreateDotExpression(El,Add,CreatePrimitiveDotExpr('toFixed',El));
Call.AddArg(ConvertElement(El.format2,AContext)); Call.AddArg(ConvertElement(El.format2,AContext));
Add:=Call; Add:=Call;
Call:=nil; Call:=nil;
@ -7189,7 +7192,7 @@ begin
if Call.Expr=nil then if Call.Expr=nil then
// default: array1.concat(array2,...) // default: array1.concat(array2,...)
Call.Expr:=CreateDotExpression(El,ConvertElement(Param0,AContext), Call.Expr:=CreateDotExpression(El,ConvertElement(Param0,AContext),
CreatePrimitiveDotExpr('concat')); CreatePrimitiveDotExpr('concat',El));
for i:=1 to length(El.Params)-1 do for i:=1 to length(El.Params)-1 do
Call.AddArg(ConvertElement(El.Params[i],AContext)); Call.AddArg(ConvertElement(El.Params[i],AContext));
Result:=Call; Result:=Call;
@ -7271,7 +7274,7 @@ begin
try try
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
ArrEl:=ConvertElement(El.Params[1],AContext); ArrEl:=ConvertElement(El.Params[1],AContext);
Call.Expr:=CreateDotExpression(El,ArrEl,CreatePrimitiveDotExpr('splice')); Call.Expr:=CreateDotExpression(El,ArrEl,CreatePrimitiveDotExpr('splice',El));
Call.AddArg(ConvertElement(El.Params[2],AContext)); Call.AddArg(ConvertElement(El.Params[2],AContext));
Call.AddArg(CreateLiteralNumber(El,1)); Call.AddArg(CreateLiteralNumber(El,1));
Call.AddArg(ConvertElement(El.Params[0],AContext)); Call.AddArg(ConvertElement(El.Params[0],AContext));
@ -7295,7 +7298,7 @@ begin
try try
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
ArrEl:=ConvertElement(El.Params[0],AContext); ArrEl:=ConvertElement(El.Params[0],AContext);
Call.Expr:=CreateDotExpression(El,ArrEl,CreatePrimitiveDotExpr('splice')); Call.Expr:=CreateDotExpression(El,ArrEl,CreatePrimitiveDotExpr('splice',El));
Call.AddArg(ConvertElement(El.Params[1],AContext)); Call.AddArg(ConvertElement(El.Params[1],AContext));
Call.AddArg(ConvertElement(El.Params[2],AContext)); Call.AddArg(ConvertElement(El.Params[2],AContext));
Result:=Call; Result:=Call;
@ -7345,7 +7348,7 @@ begin
// typeinfo(classinstance) -> classinstance.$rtti // typeinfo(classinstance) -> classinstance.$rtti
// typeinfo(classof) -> classof.$rtti // typeinfo(classof) -> classof.$rtti
Result:=ConvertElement(Param,AContext); Result:=ConvertElement(Param,AContext);
Result:=CreateDotExpression(El,Result,CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTTI])); Result:=CreateDotExpression(El,Result,CreatePrimitiveDotExpr(FBuiltInNames[pbivnRTTI],Param));
end end
else else
Result:=CreateTypeInfoRef(TypeEl,AContext,Param); Result:=CreateTypeInfoRef(TypeEl,AContext,Param);
@ -7438,7 +7441,7 @@ begin
else else
DotExpr:=TJSDotMemberExpression.Create(0,0); DotExpr:=TJSDotMemberExpression.Create(0,0);
DotExpr.Name:=TJSString(copy(AName,p+1,length(AName))); // do not lowercase DotExpr.Name:=TJSString(copy(AName,p+1,length(AName))); // do not lowercase
DotExpr.MExpr:=CreatePrimitiveDotExpr(LeftStr(AName,p-1)); DotExpr.MExpr:=CreatePrimitiveDotExpr(LeftStr(AName,p-1),Src);
Result:=DotExpr; Result:=DotExpr;
end end
else else
@ -7652,8 +7655,8 @@ Var
var var
RetSt: TJSReturnStatement; RetSt: TJSReturnStatement;
begin begin
RetSt:=TJSReturnStatement(CreateElement(TJSReturnStatement,El)); RetSt:=TJSReturnStatement(CreateElement(TJSReturnStatement,ResultEl));
RetSt.Expr:=CreatePrimitiveDotExpr(ResolverResultVar); RetSt.Expr:=CreatePrimitiveDotExpr(ResolverResultVar,ResultEl);
Add(RetSt,ResultEl); Add(RetSt,ResultEl);
end; end;
@ -7773,8 +7776,8 @@ var
exit; exit;
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
AncestorPath:=CreateReferencePath(Ancestor,ClassContext,rpkPathAndName); AncestorPath:=CreateReferencePath(Ancestor,ClassContext,rpkPathAndName);
Call.Expr:=CreatePrimitiveDotExpr(AncestorPath+'.'+MemberFuncName[Kind]+'.call'); Call.Expr:=CreatePrimitiveDotExpr(AncestorPath+'.'+MemberFuncName[Kind]+'.call',El);
Call.AddArg(CreatePrimitiveDotExpr('this')); Call.AddArg(CreatePrimitiveDotExpr('this',El));
AddToSourceElements(Src,Call); AddToSourceElements(Src,Call);
end; end;
@ -7964,7 +7967,7 @@ begin
OwnerName:=AContext.GetLocalName(El.GetModule); OwnerName:=AContext.GetLocalName(El.GetModule);
if OwnerName='' then if OwnerName='' then
OwnerName:='this'; OwnerName:='this';
Call.AddArg(CreatePrimitiveDotExpr(OwnerName)); Call.AddArg(CreatePrimitiveDotExpr(OwnerName,El));
// add parameter: string constant '"classname"' // add parameter: string constant '"classname"'
ArgEx := CreateLiteralString(El,TransformVariableName(El,AContext)); ArgEx := CreateLiteralString(El,TransformVariableName(El,AContext));
@ -7977,7 +7980,7 @@ begin
AncestorPath:=TPasClassType(Ancestor).ExternalName AncestorPath:=TPasClassType(Ancestor).ExternalName
else else
AncestorPath:=CreateReferencePath(Ancestor,AContext,rpkPathAndName); AncestorPath:=CreateReferencePath(Ancestor,AContext,rpkPathAndName);
Call.AddArg(CreatePrimitiveDotExpr(AncestorPath)); Call.AddArg(CreatePrimitiveDotExpr(AncestorPath,El));
if AncestorIsExternal then if AncestorIsExternal then
begin begin
@ -8658,7 +8661,7 @@ begin
// has nested procs -> add "var self = this;" // has nested procs -> add "var self = this;"
FuncContext.AddLocalVar(FBuiltInNames[pbivnSelf],FuncContext.ThisPas); FuncContext.AddLocalVar(FBuiltInNames[pbivnSelf],FuncContext.ThisPas);
SelfSt:=CreateVarStatement(FBuiltInNames[pbivnSelf], SelfSt:=CreateVarStatement(FBuiltInNames[pbivnSelf],
CreatePrimitiveDotExpr('this'),ImplProc); CreatePrimitiveDotExpr('this',ImplProc),ImplProc);
AddBodyStatement(SelfSt,BodyPas); AddBodyStatement(SelfSt,BodyPas);
if ImplProcScope.SelfArg<>nil then if ImplProcScope.SelfArg<>nil then
begin begin
@ -8705,13 +8708,11 @@ end;
function TPasToJSConverter.ConvertImplBlockElements(El: TPasImplBlock; function TPasToJSConverter.ConvertImplBlockElements(El: TPasImplBlock;
AContext: TConvertContext; NilIfEmpty: boolean): TJSElement; AContext: TConvertContext; NilIfEmpty: boolean): TJSElement;
var var
First, Last: TJSStatementList; First, Last: TJSStatementList;
I : Integer; I : Integer;
PasImpl: TPasImplElement; PasImpl: TPasImplElement;
JSImpl : TJSElement; JSImpl : TJSElement;
begin begin
if Not (Assigned(El.Elements) and (El.Elements.Count>0)) then if Not (Assigned(El.Elements) and (El.Elements.Count>0)) then
begin begin
@ -8834,7 +8835,7 @@ begin
// default else: throw exceptobject // default else: throw exceptobject
Last.BFalse:=TJSThrowStatement(CreateElement(TJSThrowStatement,El)); Last.BFalse:=TJSThrowStatement(CreateElement(TJSThrowStatement,El));
TJSThrowStatement(Last.BFalse).A:= TJSThrowStatement(Last.BFalse).A:=
CreatePrimitiveDotExpr(FBuiltInNames[pbivnExceptObject]); CreatePrimitiveDotExpr(FBuiltInNames[pbivnExceptObject],El);
end; end;
end end
else else
@ -9070,7 +9071,7 @@ begin
ImplContext.ThisPas:=El; ImplContext.ThisPas:=El;
ModVarName:=FBuiltInNames[pbivnModule]; ModVarName:=FBuiltInNames[pbivnModule];
AddToSourceElements(Src,CreateVarStatement(ModVarName, AddToSourceElements(Src,CreateVarStatement(ModVarName,
CreatePrimitiveDotExpr('this'),El)); CreatePrimitiveDotExpr('this',El),El));
ImplContext.AddLocalVar(ModVarName,El); ImplContext.AddLocalVar(ModVarName,El);
// add var $impl = $mod.$impl // add var $impl = $mod.$impl
@ -9384,9 +9385,9 @@ var
begin begin
aName:=GetTypeInfoName(El,AContext,ErrorEl); aName:=GetTypeInfoName(El,AContext,ErrorEl);
if aName=FBuiltInNames[pbivnRTTILocal] then if aName=FBuiltInNames[pbivnRTTILocal] then
Result:=CreatePrimitiveDotExpr(aName) Result:=CreatePrimitiveDotExpr(aName,El)
else if LeftStr(aName,length(FBuiltInNames[pbivnRTL])+1)=FBuiltInNames[pbivnRTL]+'.' then else if LeftStr(aName,length(FBuiltInNames[pbivnRTL])+1)=FBuiltInNames[pbivnRTL]+'.' then
Result:=CreatePrimitiveDotExpr(aName) Result:=CreatePrimitiveDotExpr(aName,El)
else else
begin begin
CurEl:=El; CurEl:=El;
@ -9878,7 +9879,7 @@ begin
if El.ExceptObject<>Nil then if El.ExceptObject<>Nil then
E:=ConvertElement(El.ExceptObject,AContext) E:=ConvertElement(El.ExceptObject,AContext)
else else
E:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnExceptObject]); E:=CreatePrimitiveDotExpr(FBuiltInNames[pbivnExceptObject],El);
T:=TJSThrowStatement(CreateElement(TJSThrowStatement,El)); T:=TJSThrowStatement(CreateElement(TJSThrowStatement,El));
T.A:=E; T.A:=E;
Result:=T; Result:=T;
@ -10815,7 +10816,7 @@ begin
begin begin
// aChar -> aChar.charCodeAt() // aChar -> aChar.charCodeAt()
Call:=TJSCallExpression(CreateElement(TJSCallExpression,Expr)); Call:=TJSCallExpression(CreateElement(TJSCallExpression,Expr));
Call.Expr:=CreateDotExpression(Expr,Result,CreatePrimitiveDotExpr('charCodeAt')); Call.Expr:=CreateDotExpression(Expr,Result,CreatePrimitiveDotExpr('charCodeAt',Expr));
Result:=Call; Result:=Call;
end end
else if ExprResolved.BaseType=btContext then else if ExprResolved.BaseType=btContext then
@ -11214,12 +11215,17 @@ function TPasToJSConverter.CreateReferencePathExpr(El: TPasElement;
): TJSElement; ): TJSElement;
var var
Name: String; Name: String;
Src: TPasElement;
begin begin
{$IFDEF VerbosePas2JS} {$IFDEF VerbosePas2JS}
writeln('TPasToJSConverter.CreateReferencePathExpr El="',GetObjName(El),'" El.Parent=',GetObjName(El.Parent)); writeln('TPasToJSConverter.CreateReferencePathExpr El="',GetObjName(El),'" El.Parent=',GetObjName(El.Parent));
{$ENDIF} {$ENDIF}
Name:=CreateReferencePath(El,AContext,rpkPathAndName,Full,Ref); Name:=CreateReferencePath(El,AContext,rpkPathAndName,Full,Ref);
Result:=CreatePrimitiveDotExpr(Name); if Ref<>nil then
Src:=Ref.Element
else
Src:=nil;
Result:=CreatePrimitiveDotExpr(Name,Src);
end; end;
procedure TPasToJSConverter.CreateProcedureCall(var Call: TJSCallExpression; procedure TPasToJSConverter.CreateProcedureCall(var Call: TJSCallExpression;
@ -11467,12 +11473,12 @@ begin
// GetExpr: this.p.readvar // GetExpr: this.p.readvar
// Will create "{p:GetPathExpr, get:function(){return GetExpr;}, // Will create "{p:GetPathExpr, get:function(){return GetExpr;},
// set:function(v){GetExpr = v;}}" // set:function(v){GetExpr = v;}}"
GetPathExpr:=CreatePrimitiveDotExpr(LeftStr(GetPath,GetDotPos-1)); GetPathExpr:=CreatePrimitiveDotExpr(LeftStr(GetPath,GetDotPos-1),El);
GetExpr:=CreateDotExpression(El,CreatePrimitiveDotExpr('this.'+GetPathName), GetExpr:=CreateDotExpression(El,CreatePrimitiveDotExpr('this.'+GetPathName,El),
CreatePrimitiveDotExpr(copy(GetPath,GetDotPos+1))); CreatePrimitiveDotExpr(copy(GetPath,GetDotPos+1),El));
if ParamContext.Setter=nil then if ParamContext.Setter=nil then
SetExpr:=CreateDotExpression(El,CreatePrimitiveDotExpr('this.'+GetPathName), SetExpr:=CreateDotExpression(El,CreatePrimitiveDotExpr('this.'+GetPathName,El),
CreatePrimitiveDotExpr(copy(GetPath,GetDotPos+1))); CreatePrimitiveDotExpr(copy(GetPath,GetDotPos+1),El));
end end
else else
begin begin
@ -11480,7 +11486,7 @@ begin
GetExpr:=FullGetter; GetExpr:=FullGetter;
FullGetter:=nil; FullGetter:=nil;
if ParamContext.Setter=nil then if ParamContext.Setter=nil then
SetExpr:=CreatePrimitiveDotExpr(GetPath); SetExpr:=CreatePrimitiveDotExpr(GetPath,El);
end; end;
if ParamContext.Setter<>nil then if ParamContext.Setter<>nil then
@ -11496,15 +11502,15 @@ begin
if LeftStr(GetPath,GetDotPos)=LeftStr(SetPath,SetDotPos) then if LeftStr(GetPath,GetDotPos)=LeftStr(SetPath,SetDotPos) then
begin begin
// use GetPathExpr for setter // use GetPathExpr for setter
SetExpr:=CreateDotExpression(El,CreatePrimitiveDotExpr('this.'+GetPathName), SetExpr:=CreateDotExpression(El,CreatePrimitiveDotExpr('this.'+GetPathName,El),
CreatePrimitiveDotExpr(copy(SetPath,GetDotPos+1))); CreatePrimitiveDotExpr(copy(SetPath,GetDotPos+1),El));
end end
else else
begin begin
// setter needs its own SetPathExpr // setter needs its own SetPathExpr
SetPathExpr:=CreatePrimitiveDotExpr(LeftStr(SetPath,SetDotPos-1)); SetPathExpr:=CreatePrimitiveDotExpr(LeftStr(SetPath,SetDotPos-1),El);
SetExpr:=CreateDotExpression(El,CreatePrimitiveDotExpr('this.'+SetPathName), SetExpr:=CreateDotExpression(El,CreatePrimitiveDotExpr('this.'+SetPathName,El),
CreatePrimitiveDotExpr(copy(SetPath,GetDotPos+1))); CreatePrimitiveDotExpr(copy(SetPath,GetDotPos+1),El));
end; end;
end; end;
end; end;
@ -11523,12 +11529,12 @@ begin
// SetExpr: this.p.i // SetExpr: this.p.i
DotExpr:=TJSDotMemberExpression(FullGetter); DotExpr:=TJSDotMemberExpression(FullGetter);
GetPathExpr:=DotExpr.MExpr; GetPathExpr:=DotExpr.MExpr;
DotExpr.MExpr:=CreatePrimitiveDotExpr('this.'+GetPathName); DotExpr.MExpr:=CreatePrimitiveDotExpr('this.'+GetPathName,El);
GetExpr:=DotExpr; GetExpr:=DotExpr;
FullGetter:=nil; FullGetter:=nil;
SetExpr:=CreateDotExpression(El, SetExpr:=CreateDotExpression(El,
CreatePrimitiveDotExpr('this.'+GetPathName), CreatePrimitiveDotExpr('this.'+GetPathName,El),
CreatePrimitiveDotExpr(String(DotExpr.Name))); CreatePrimitiveDotExpr(String(DotExpr.Name),El));
end end
else if FullGetter.ClassType=TJSBracketMemberExpression then else if FullGetter.ClassType=TJSBracketMemberExpression then
begin begin
@ -11544,12 +11550,12 @@ begin
ParamExpr:=BracketExpr.Name; ParamExpr:=BracketExpr.Name;
// create "a:value" // create "a:value"
BracketExpr.Name:=CreatePrimitiveDotExpr('this.'+ParamName); BracketExpr.Name:=CreatePrimitiveDotExpr('this.'+ParamName,El);
AddVar(ParamName,ParamExpr); AddVar(ParamName,ParamExpr);
// create GetPathExpr "this.arr" // create GetPathExpr "this.arr"
GetPathExpr:=BracketExpr.MExpr; GetPathExpr:=BracketExpr.MExpr;
BracketExpr.MExpr:=CreatePrimitiveDotExpr('this.'+GetPathName); BracketExpr.MExpr:=CreatePrimitiveDotExpr('this.'+GetPathName,El);
// GetExpr "this.p[this.a]" // GetExpr "this.p[this.a]"
GetExpr:=BracketExpr; GetExpr:=BracketExpr;
@ -11558,8 +11564,8 @@ begin
// SetExpr "this.p[this.a]" // SetExpr "this.p[this.a]"
BracketExpr:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression,El)); BracketExpr:=TJSBracketMemberExpression(CreateElement(TJSBracketMemberExpression,El));
SetExpr:=BracketExpr; SetExpr:=BracketExpr;
BracketExpr.MExpr:=CreatePrimitiveDotExpr('this.'+GetPathName); BracketExpr.MExpr:=CreatePrimitiveDotExpr('this.'+GetPathName,El);
BracketExpr.Name:=CreatePrimitiveDotExpr('this.'+ParamName); BracketExpr.Name:=CreatePrimitiveDotExpr('this.'+ParamName,El);
end end
else else
@ -11577,7 +11583,7 @@ begin
// create SetExpr = v; // create SetExpr = v;
AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El)); AssignSt:=TJSSimpleAssignStatement(CreateElement(TJSSimpleAssignStatement,El));
AssignSt.LHS:=SetExpr; AssignSt.LHS:=SetExpr;
AssignSt.Expr:=CreatePrimitiveDotExpr(TempRefObjSetterArgName); AssignSt.Expr:=CreatePrimitiveDotExpr(TempRefObjSetterArgName,El);
SetExpr:=AssignSt; SetExpr:=AssignSt;
end end
else if (SetExpr.ClassType=TJSCallExpression) then else if (SetExpr.ClassType=TJSCallExpression) then
@ -11648,7 +11654,7 @@ begin
// create "T.isPrototypeOf(exceptObject)" // create "T.isPrototypeOf(exceptObject)"
Call:=CreateCallExpression(El); Call:=CreateCallExpression(El);
Call.Expr:=DotExpr; Call.Expr:=DotExpr;
Call.AddArg(CreatePrimitiveDotExpr(FBuiltInNames[pbivnExceptObject])); Call.AddArg(CreatePrimitiveDotExpr(FBuiltInNames[pbivnExceptObject],El));
IfSt.Cond:=Call; IfSt.Cond:=Call;
if El.VarEl<>nil then if El.VarEl<>nil then
@ -11658,7 +11664,7 @@ begin
ListLast:=ListFirst; ListLast:=ListFirst;
IfSt.BTrue:=ListFirst; IfSt.BTrue:=ListFirst;
V:=CreateVarStatement(TransformVariableName(El,El.VariableName,AContext), V:=CreateVarStatement(TransformVariableName(El,El.VariableName,AContext),
CreatePrimitiveDotExpr(FBuiltInNames[pbivnExceptObject]),El); CreatePrimitiveDotExpr(FBuiltInNames[pbivnExceptObject],El),El);
ListFirst.A:=V; ListFirst.A:=V;
// add statements // add statements
AddToStatementList(ListFirst,ListLast,ConvertElement(El.Body,AContext),El); AddToStatementList(ListFirst,ListLast,ConvertElement(El.Body,AContext),El);
@ -11867,7 +11873,7 @@ const
VarAssignSt.LHS:=CreateSubDeclNameExpr(PasVar,PasVar.Name,FuncContext); VarAssignSt.LHS:=CreateSubDeclNameExpr(PasVar,PasVar.Name,FuncContext);
VarDotExpr:=TJSDotMemberExpression(CreateElement(TJSDotMemberExpression,PasVar)); VarDotExpr:=TJSDotMemberExpression(CreateElement(TJSDotMemberExpression,PasVar));
VarAssignSt.Expr:=VarDotExpr; VarAssignSt.Expr:=VarDotExpr;
VarDotExpr.MExpr:=CreatePrimitiveDotExpr(SrcParamName); VarDotExpr.MExpr:=CreatePrimitiveDotExpr(SrcParamName,PasVar);
VarDotExpr.Name:=TJSString(TransformVariableName(PasVar,FuncContext)); VarDotExpr.Name:=TJSString(TransformVariableName(PasVar,FuncContext));
if (AContext.Resolver<>nil) then if (AContext.Resolver<>nil) then
begin begin
@ -12090,7 +12096,7 @@ begin
IfSt:=TJSIfStatement(CreateElement(TJSIfStatement,El)); IfSt:=TJSIfStatement(CreateElement(TJSIfStatement,El));
AddToStatementList(BodyFirst,BodyLast,IfSt,El); AddToStatementList(BodyFirst,BodyLast,IfSt,El);
FD.Body.A:=BodyFirst; FD.Body.A:=BodyFirst;
IfSt.Cond:=CreatePrimitiveDotExpr(SrcParamName); IfSt.Cond:=CreatePrimitiveDotExpr(SrcParamName,El);
// add clone statements // add clone statements
AddCloneStatements(IfSt,FuncContext); AddCloneStatements(IfSt,FuncContext);
// add init default statements // add init default statements
@ -12120,7 +12126,7 @@ begin
// ); // );
Call2:=CreateCallExpression(El); Call2:=CreateCallExpression(El);
Call2.Expr:=CreateDotExpression(El,Call, Call2.Expr:=CreateDotExpression(El,Call,
CreatePrimitiveDotExpr(FBuiltInNames[pbifnRTTIAddFields])); CreatePrimitiveDotExpr(FBuiltInNames[pbifnRTTIAddFields],El));
Call:=Call2; Call:=Call2;
AddRTTIFields(Call.Args,ListFirst,ListLast); AddRTTIFields(Call.Args,ListFirst,ListLast);
end; end;

View File

@ -92,6 +92,8 @@ begin
end; end;
procedure TPas2JSMapper.SetCurElement(const AValue: TJSElement); procedure TPas2JSMapper.SetCurElement(const AValue: TJSElement);
var
C: TClass;
begin begin
{$IFDEF VerboseSrcMap} {$IFDEF VerboseSrcMap}
system.write('TPas2JSWriter.SetCurElement ',CurLine,',',CurColumn); system.write('TPas2JSWriter.SetCurElement ',CurLine,',',CurColumn);
@ -101,6 +103,12 @@ begin
system.writeln(' NIL'); system.writeln(' NIL');
{$ENDIF} {$ENDIF}
inherited SetCurElement(AValue); inherited SetCurElement(AValue);
C:=AValue.ClassType;
if (C=TJSStatementList)
or (C=TJSEmptyBlockStatement)
or (C=TJSEmptyStatement) then
exit; // do not switch position on brackets
if (AValue<>nil) and (AValue.Source<>'') then if (AValue<>nil) and (AValue.Source<>'') then
begin begin
if (FSrcFilename<>AValue.Source) if (FSrcFilename<>AValue.Source)

View File

@ -59,7 +59,8 @@ type
procedure TestIfBegin; procedure TestIfBegin;
procedure TestFor; procedure TestFor;
procedure TestFunction; procedure TestFunction;
procedure Test; procedure TestExternalObjCall;
procedure TestBracketAccessor;
end; end;
implementation implementation
@ -120,89 +121,12 @@ end;
procedure TCustomTestSrcMap.WriteSrcMapLine(GeneratedLine: integer); procedure TCustomTestSrcMap.WriteSrcMapLine(GeneratedLine: integer);
var var
JS, Origins, Addition: String; JS, Origins: String;
GeneratedCol: integer; // 0-based
i, diff, GenColStep: Integer;
aSeg: TSourceMapSegment;
begin begin
JS:=JSSource[GeneratedLine-1]; JS:=JSSource[GeneratedLine-1];
Origins:=''; DebugSrcMapLine(GeneratedLine,JS,SrcMap,Origins);
GeneratedCol:=0;// 0-based writeln(JS);
i:=SrcMap.IndexOfSegmentAt(GeneratedLine,GeneratedCol); writeln(Origins);
aSeg:=nil;
if i<0 then
begin
// no segment at line start
i:=0;
if (i=SrcMap.Count) then
aSeg:=nil
else
aSeg:=SrcMap[i];
if (aSeg=nil) or (aSeg.GeneratedLine>GeneratedLine) then
begin
// no segment in line
for i:=1 to length(JS) do Origins:=Origins+'?';
writeln(JS);
writeln(Origins);
exit;
end
else
begin
// show "?" til start of first segment
for i:=1 to aSeg.GeneratedColumn do Origins:=Origins+'?';
end;
end
else
aSeg:=SrcMap[i];
repeat
Addition:='';
if (aSeg.GeneratedLine=GeneratedLine) and (aSeg.GeneratedColumn=GeneratedCol) then
begin
// segment starts here -> write "|line,col"
Addition:='|'+IntToStr(aSeg.SrcLine)+','+IntToStr(aSeg.SrcColumn);
Origins:=Origins+Addition;
end;
inc(i);
// skip segments at same GeneratedLine/Col
while (i<SrcMap.Count) do
begin
aSeg:=SrcMap[i];
if (aSeg.GeneratedLine=GeneratedLine) and (aSeg.GeneratedColumn=GeneratedCol) then
inc(i)
else
break;
end;
if (i=SrcMap.Count) then
aSeg:=nil
else
aSeg:=SrcMap[i];
if (aSeg=nil) or (aSeg.GeneratedLine>GeneratedLine) then
begin
// in the last segment
while length(Origins)<length(JS) do
Origins:=Origins+'.';
writeln(JS);
writeln(Origins);
exit;
end;
// there is another segment in this line
// -> align JS and Origins
GenColStep:=aSeg.GeneratedColumn-GeneratedCol;
diff:=GenColStep-length(Addition);
if diff<0 then
// for example:
// JS: if(~~e)~~~{
// Origins: |12,3|12,5|12,7
Insert(StringOfChar('~',-diff),JS,length(Origins)-length(Addition)+1+GenColStep)
else
while diff>0 do
begin
Origins:=Origins+'.';
dec(diff);
end;
GeneratedCol:=aSeg.GeneratedColumn;
until false;
end; end;
{ TTestSrcMap } { TTestSrcMap }
@ -292,9 +216,48 @@ begin
CheckSrcMap('TestFunction'); CheckSrcMap('TestFunction');
end; end;
procedure TTestSrcMap.Test; procedure TTestSrcMap.TestExternalObjCall;
begin begin
StartProgram(false);
Add([
'{$modeswitch externalclass}',
'type',
' TJSConsole = class external name ''Console''',
' Public',
' procedure log(Obj1 : JSValue); varargs;',
' end;',
'var console : TJSConsole; external name ''window.console'';',
' xhrstatus: longint;',
'begin',
' console.log(''state'');',
' if xhrstatus=200 then',
' begin',
' xhrstatus:=3;',
' xhrstatus:=4;',
' end;']);
ConvertProgram;
CheckSrcMap('TestExternalObjCall');
end;
procedure TTestSrcMap.TestBracketAccessor;
begin
StartProgram(false);
Add([
'{$modeswitch externalclass}',
'type',
' TJSObject = class external name ''Object''',
' private',
' function GetProperties(Name: String): JSValue; external name ''[]'';',
' Public',
' property Properties[Name: string]: JSValue read GetProperties;',
' end;',
'var Obj : TJSObject;',
' j: JSValue;',
'begin',
' j:=Obj.Properties[''state''];',
' ']);
ConvertProgram;
CheckSrcMap('TestExternalObjCall');
end; end;
Initialization Initialization