Browse Source

--- Merging r34038 into '.':
U packages/pastojs/tests/tcconverter.pp
--- Recording mergeinfo for merge of r34038 into '.':
U .
--- Merging r34065 into '.':
U packages/fcl-web/src/base/fpoauth2ini.pp
--- Recording mergeinfo for merge of r34065 into '.':
G .
--- Merging r34096 into '.':
U packages/fcl-js/src/jsbase.pp
--- Recording mergeinfo for merge of r34096 into '.':
G .
--- Merging r34196 into '.':
U packages/fcl-json/src/jsonconf.pp
--- Recording mergeinfo for merge of r34196 into '.':
G .
--- Merging r34199 into '.':
U packages/fcl-json/src/jsonscanner.pp
--- Recording mergeinfo for merge of r34199 into '.':
G .
--- Merging r34202 into '.':
U packages/pastojs/src/fppas2js.pp
--- Recording mergeinfo for merge of r34202 into '.':
G .
--- Merging r34204 into '.':
U packages/fcl-js/tests/testjs.lpr
U packages/fcl-js/src/jsparser.pp
U packages/fcl-js/src/jswriter.pp
U packages/fcl-js/src/jstree.pp
U packages/fcl-js/src/jstoken.pp
--- Recording mergeinfo for merge of r34204 into '.':
G .
--- Merging r34206 into '.':
G packages/pastojs/src/fppas2js.pp
--- Recording mergeinfo for merge of r34206 into '.':
G .
--- Merging r34212 into '.':
G packages/fcl-js/src/jsbase.pp
--- Recording mergeinfo for merge of r34212 into '.':
G .
--- Merging r34213 into '.':
G packages/fcl-js/src/jswriter.pp
--- Recording mergeinfo for merge of r34213 into '.':
G .
--- Merging r34215 into '.':
G packages/pastojs/src/fppas2js.pp
--- Recording mergeinfo for merge of r34215 into '.':
G .
--- Merging r34217 into '.':
G packages/fcl-js/src/jswriter.pp
G packages/fcl-js/src/jstree.pp
--- Recording mergeinfo for merge of r34217 into '.':
G .
--- Merging r34218 into '.':
U packages/pastojs/tests/testpas2js.lpi
G packages/pastojs/tests/tcconverter.pp
G packages/pastojs/src/fppas2js.pp
--- Recording mergeinfo for merge of r34218 into '.':
G .
--- Merging r34226 into '.':
U packages/fcl-js/tests/tcwriter.pp
G packages/fcl-js/src/jswriter.pp
--- Recording mergeinfo for merge of r34226 into '.':
G .
--- Merging r34227 into '.':
G packages/pastojs/src/fppas2js.pp
G packages/pastojs/tests/tcconverter.pp
--- Recording mergeinfo for merge of r34227 into '.':
G .

# revisions: 34038,34065,34096,34196,34199,34202,34204,34206,34212,34213,34215,34217,34218,34226,34227

git-svn-id: branches/fixes_3_0@35975 -

marco 8 years ago
parent
commit
a0da5c15d7

+ 14 - 6
packages/fcl-js/src/jsbase.pp

@@ -80,25 +80,33 @@ end;
 function TJSValue.GetAsNumber: TJSNumber;
 begin
   If (ValueType=jstNumber) then
-    Result:=FValue.F;
+    Result:=FValue.F
+  else
+    Result:=0.0;
 end;
 
 function TJSValue.GetAsObject: TObject;
 begin
   If (ValueType=jstObject) then
-    Result:=TObject(FValue.P);
+    Result:=TObject(FValue.P)
+  else
+    Result:=nil;
 end;
 
 function TJSValue.GetAsReference: TObject;
 begin
   If (ValueType=jstReference) then
-    Result:=TObject(FValue.P);
+    Result:=TObject(FValue.P)
+  else
+    Result:=nil;
 end;
 
 function TJSValue.GetAsString: TJSString;
 begin
   If (ValueType=jstString) then
-    Result:=String(FValue.P);
+    Result:=TJSString(FValue.P)
+  else
+    Result:='';
 end;
 
 function TJSValue.GetIsNull: Boolean;
@@ -156,7 +164,7 @@ end;
 procedure TJSValue.SetAsString(const AValue: TJSString);
 begin
   ClearValue(jstString);
-  String(FValue.P):=AValue;
+  TJSString(FValue.P):=AValue;
 end;
 
 procedure TJSValue.SetIsNull(const AValue: Boolean);
@@ -191,7 +199,7 @@ end;
 
 Constructor TJSValue.Create(AString: TJSString);
 begin
-  AsString:=AString
+  AsString:=AString;
 end;
 
 Destructor TJSValue.Destroy;

+ 4 - 19
packages/fcl-js/src/jsparser.pp

@@ -25,8 +25,6 @@ Type
     FPrevious,
     FCurrent : TJSToken;
     FCurrentString : String;
-    FNextNewLine : Boolean;
-    FNextBol : Boolean;
     FFreeScanner : Boolean;
     FCurrentVars : TJSElementNodes;
     FPeekToken: TJSToken;
@@ -557,8 +555,6 @@ function TJSParser.ParseObjectLiteral: TJSElement;
 Var
   N : TJSObjectLiteral;
   E : TJSObjectLiteralElement;
-  I : Integer;
-
 begin
   Consume(tjsCurlyBraceOpen);
   N:=TJSObjectLiteral(CreateElement(TJSObjectLiteral));
@@ -618,9 +614,6 @@ function TJSParser.ParseStringLiteral: TJSElement;
 
 Var
   L : TJSLiteral;
-  D : Double;
-  I : Integer;
-
 begin
     {$ifdef debugparser} Writeln('Parsing string literal');{$endif debugparser}
   Result:=Nil;
@@ -746,7 +739,6 @@ Var
   M  : TJSDotMemberExpression;
   N  : TJSNewMemberExpression;
   B  : TJSBracketMemberExpression;
-  C : TJSCallExpression;
   Done : Boolean;
 
 begin
@@ -758,7 +750,7 @@ begin
                   N:=TJSNewMemberExpression(CreateElement(TJSNewMemberExpression));
                   try
                     Result:=N;
-                    N.Mexpr:=ParseMemberExpression();
+                    N.MExpr:=ParseMemberExpression();
                     if (CurrentToken=tjsBraceOpen) then
                       N.Args:=ParseArguments;
                   except
@@ -1378,7 +1370,6 @@ end;
 function TJSParser.ParseVariableStatement : TJSElement;
 
 Var
-  E : TJSElement;
   V : TJSVariableStatement;
 
 begin
@@ -1429,7 +1420,7 @@ begin
     I:=TJSIfStatement(CreateElement(TJSIfStatement));
     I.Cond:=C;
     I.BTrue:=Btrue;
-    I.bfalse:=BFalse;
+    I.BFalse:=BFalse;
     Result:=I;
   except
     FreeAndNil(C);
@@ -1641,8 +1632,6 @@ function TJSParser.ParseWithStatement : TJSElement;
 
 Var
   W : TJSWithStatement;
-  N : TJSElement;
-
 begin
   W:=TJSWithStatement(CreateElement(TJSWithStatement));
   try
@@ -1655,6 +1644,7 @@ begin
     FreeAndNil(W);
     Raise;
   end;
+  Result:=W;
 end;
 
 function TJSParser.ParseSwitchStatement : TJSElement;
@@ -1662,7 +1652,6 @@ function TJSParser.ParseSwitchStatement : TJSElement;
 
 Var
   N : TJSSwitchStatement;
-  C : TJSElement;
   Ca : TJSCaseElement;
 
 begin
@@ -1883,8 +1872,6 @@ function TJSParser.ParseLabeledStatement : TJSElement;
 Var
   OL : TJSLabelSet;
   LS : TJSLabeledStatement;
-  LN : String;
-
 begin
   LS:=TJSLabeledStatement(CreateElement(TJSLabeledStatement));
   try
@@ -2046,7 +2033,7 @@ begin
           If (PeekNextToken<>tjsBraceOpen) then
             begin
             F:=Self.ParseFunctionDeclaration;
-            Result.functions.AddNode.Node:=F;
+            Result.Functions.AddNode.Node:=F;
             end
           else
             begin
@@ -2095,8 +2082,6 @@ end;
 Function TJSParser.ParseProgram: TJSFunctionDeclarationStatement;
 
 Var
-  F : TJSFunctionDeclarationStatement;
-  FD : TJSFuncDef;
   B : TJSElement;
 begin
   {$ifdef debugparser} Writeln('>>> Entering FunctionDeclarationStatement');{$endif}

+ 1 - 1
packages/fcl-js/src/jstoken.pp

@@ -8,7 +8,7 @@ type
 
   TJSToken = (tjsUnknown,
      // Specials
-     tjsEOF,tjsWhiteSpace,tjsChar,tjsString, tjsIdentifier,tjsNumber, tjsComment,tjsREGEX, tjsRESERVED,
+     tjsEOF,tjsWhiteSpace,tjsChar,tjsString{this bites TJSString}, tjsIdentifier,tjsNumber, tjsComment,tjsREGEX, tjsRESERVED,
      tjsANDAND, tjsANDEQ,
      tjsBraceOpen,tjsBraceClose,tjsSQuaredBraceOpen,tjsSQuaredBraceClose,tjsCurlyBraceOpen,tjsCurlyBraceClose,
      tjsCOMMA,tjsCOLON,  tjsDOT,tjsSEMICOLON, tjsASSIGN,tjsGT,tjsLT, tjsConditional,

+ 188 - 147
packages/fcl-js/src/jstree.pp

@@ -73,45 +73,47 @@ Type
   TJSObject = Class(TObject);
 
 
-    { TJSLabelSet }
-
-    TJSLabelSet = Class(TJSObject)
-    private
-      FCOnt: Boolean;
-      FNext: TJSLabelSet;
-      FTarget: Cardinal;
-    Public
-      Property Target : Cardinal Read FTarget Write FTarget;
-      Property Next : TJSLabelSet Read FNext Write FNext; // Linked list
-      Property Continuable : Boolean Read FCOnt Write FCont;
-    end;
+  { TJSLabelSet }
 
-    { TJSLabel }
-
-    TJSLabel = Class(TJSObject)
-    private
-      FLabelSet: TJSLabelSet;
-      FLocationLine: Integer;
-      FLocationPos: Integer;
-      FLocationSource: String;
-      FName: String;
-      FNext: TJSLabel;
-    Public
-      Property Name : String Read FName Write FName;
-      Property LabelSet : TJSLabelSet Read FLabelSet Write FLabelSet;
-      Property LocationSource : String Read FLocationSource Write FLocationSource;
-      Property LocationLine : Integer Read FLocationLine Write FLocationLine;
-      Property LocationPos : Integer Read FLocationPos Write FLocationPos;
-      Property Next : TJSLabel Read FNext Write FNext;
-    end;
+  TJSLabelSet = Class(TJSObject)
+  private
+    FCont: Boolean;
+    FNext: TJSLabelSet;
+    FTarget: Cardinal;
+  Public
+    Property Target : Cardinal Read FTarget Write FTarget;
+    Property Next : TJSLabelSet Read FNext Write FNext; // Linked list
+    Property Continuable : Boolean Read FCont Write FCont;
+  end;
 
-  { TJSFuncDef }
+  { TJSLabel }
+
+  TJSLabel = Class(TJSObject)
+  private
+    FLabelSet: TJSLabelSet;
+    FLocationLine: Integer;
+    FLocationPos: Integer;
+    FLocationSource: String;
+    FName: String;
+    FNext: TJSLabel;
+  Public
+    Property Name : String Read FName Write FName;
+    Property LabelSet : TJSLabelSet Read FLabelSet Write FLabelSet;
+    Property LocationSource : String Read FLocationSource Write FLocationSource;
+    Property LocationLine : Integer Read FLocationLine Write FLocationLine;
+    Property LocationPos : Integer Read FLocationPos Write FLocationPos;
+    Property Next : TJSLabel Read FNext Write FNext;
+  end;
+
+  TJSString = jsbase.TJSString; // beware of jstoken.tjsString
+
+  { TJSFuncDef - e.g. 'function Name(Params)Body' }
 
   TJSFuncDef = Class(TJSObject)
   private
     FBody: TJSFunctionBody;
     FIsEmpty: Boolean;
-    FName: String;
+    FName: TJSString;
     FParams: TStrings;
     procedure SetParams(const AValue: TStrings);
   Public
@@ -119,13 +121,13 @@ Type
     Destructor Destroy; override;
     Property Params : TStrings Read FParams Write SetParams;
     Property Body : TJSFunctionBody Read FBody Write FBody;
-    Property Name : String Read FName Write FName;
+    Property Name : TJSString Read FName Write FName;
     Property IsEmpty : Boolean Read FIsEmpty Write FIsEmpty;
   end;
 
-  TJSString = WideString;
+  { TJSElement }
 
-  TJSElement = Class (TJSObject)
+  TJSElement = Class(TJSObject)
   private
     FFlags: TJSElementFlags;
     FLine: Integer;
@@ -140,9 +142,12 @@ Type
   end;
   TJSElementClass = Class of TJSElement;
 
-  { TJSEmptyBlockStatement }
+  { TJSEmptyBlockStatement - empty curly brackets }
 
   TJSEmptyBlockStatement = Class(TJSElement);
+
+  { TJSEmptyStatement - a dummy placeholder, needs sometimes a single semicolon }
+
   TJSEmptyStatement = Class(TJSElement);
 
   { TJSLiteral }
@@ -156,15 +161,6 @@ Type
     Property Value : TJSValue Read FValue Write FValue;
   end;
 
-(*  { TJSStringLiteral }
-
-  TJSStringLiteral = Class(TJSElement)
-  private
-    FValue: TJSString;
-  Public
-    Property Value : TJSString Read FValue Write FValue;
-  end;
-*)
   { TJSRegularExpressionLiteral }
 
   TJSRegularExpressionLiteral = Class(TJSElement)
@@ -182,18 +178,20 @@ Type
     Property Argv[AIndex : integer] : TJSValue Read GetA Write SetA;
   end;
 
-  { TJSPrimaryExpressionIdent }
   TJSPrimaryExpression = Class(TJSElement);
 
+  TJSPrimaryExpressionThis = Class(TJSPrimaryExpression); // 'this'
+
+  { TJSPrimaryExpressionIdent }
+
   TJSPrimaryExpressionIdent = Class(TJSPrimaryExpression)
   private
     FName: TJSString;
   Public
     Property Name : TJSString Read FName Write FName;
   end;
-  TJSPrimaryExpressionThis = Class(TJSPrimaryExpression);
 
-  { TJSArrayLiteralElement }
+  { TJSArrayLiteralElement - an item of a TJSArrayLiteralElements }
 
   TJSArrayLiteralElement = Class(TCollectionItem)
   private
@@ -205,7 +203,7 @@ Type
     Property ElementIndex : Integer Read FFindex Write FFIndex;
   end;
 
-  { TJSArrayLiteralElements }
+  { TJSArrayLiteralElements - Elements property of TJSArrayLiteral }
 
   TJSArrayLiteralElements = Class(TCollection)
   private
@@ -226,7 +224,7 @@ Type
     Property Elements : TJSArrayLiteralElements Read FElements;
   end;
 
-  { TJSObjectLiteralElement }
+  { TJSObjectLiteralElement - an item of TJSObjectLiteralElements }
 
   TJSObjectLiteralElement = Class(TCollectionItem)
   private
@@ -238,7 +236,7 @@ Type
     Property Name : TJSString Read FName Write FName;
   end;
 
-  { TJSObjectLiteralElements }
+  { TJSObjectLiteralElements - Elements property of TJSObjectLiteral }
 
   TJSObjectLiteralElements = Class(TCollection)
   private
@@ -263,17 +261,17 @@ Type
 
   TJSArguments = Class(TJSArrayLiteral);
 
-  { TJSMemberExpression }
+  { TJSMemberExpression - base class }
 
   TJSMemberExpression = Class(TJSElement)
   private
     FMexpr: TJSElement;
   Public
     Destructor Destroy; override;
-    Property Mexpr : TJSElement Read FMexpr Write FMexpr;
+    Property MExpr : TJSElement Read FMexpr Write FMexpr;
   end;
 
-  { TJSNewMemberExpression }
+  { TJSNewMemberExpression - e.g. 'new MExpr(Args)' }
 
   TJSNewMemberExpression = Class(TJSMemberExpression)
   private
@@ -283,7 +281,7 @@ Type
     Property Args : TJSArguments Read FArgs Write FArgs;
   end;
 
-  { TJSDotMemberExpression }
+  { TJSDotMemberExpression - e.g. 'MExpr.Name' }
 
   TJSDotMemberExpression = Class(TJSMemberExpression)
   private
@@ -292,7 +290,7 @@ Type
     Property Name : TJSString Read FName Write FName;
   end;
 
-  { TJSBracketMemberExpression }
+  { TJSBracketMemberExpression - e.g. 'MExpr[Name]' }
 
   TJSBracketMemberExpression = Class(TJSMemberExpression)
   private
@@ -302,7 +300,7 @@ Type
     Property Name : TJSElement Read FName Write FName;
   end;
 
-  { TJSCallExpression }
+  { TJSCallExpression - e.g. 'Expr(Args)'}
 
   TJSCallExpression = Class(TJSElement)
   private
@@ -314,7 +312,7 @@ Type
     Property Args : TJSArguments Read FArgs Write FArgs;
   end;
 
-  { TJSUnary }
+  { TJSUnary - e.g. 'PrefixOperator A PostFixOperator', '--i' }
 
   TJSUnary = Class(TJSElement)
   private
@@ -329,87 +327,102 @@ Type
   end;
   TJSUnaryClass = class of TJSUnary;
 
-  { TJSVariableStatement }
+  { TJSVariableStatement - e.g. 'var A' }
+
   TJSVariableStatement = Class(TJSUnary);
+
+  { TJSExpressionStatement - ? }
+
   TJSExpressionStatement = Class(TJSUnary);
 
-  { TJSThrowStatement }
+  { TJSThrowStatement - e.g. 'throw A' }
 
   TJSThrowStatement = Class(TJSUnary)
+  Public
     Class function PrefixOperatorToken : tjsToken; Override;
   end;
 
   TJSUnaryExpression = Class(TJSUnary);
 
-  { TJSUnaryDeleteExpression }
+  { TJSUnaryDeleteExpression - e.g. 'delete A' }
 
   TJSUnaryDeleteExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryVoidExpression }
+  { TJSUnaryVoidExpression - e.g. 'void A' }
 
   TJSUnaryVoidExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryTypeOfExpression }
+  { TJSUnaryTypeOfExpression - e.g. 'typeof A' }
 
   TJSUnaryTypeOfExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryPrePlusPlusExpression }
+  { TJSUnaryPrePlusPlusExpression - e.g. '++A' }
 
   TJSUnaryPrePlusPlusExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryPreMinusMinusExpression }
+  { TJSUnaryPreMinusMinusExpression - e.g. '--A' }
 
   TJSUnaryPreMinusMinusExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryPlusExpression }
+  { TJSUnaryPlusExpression - e.g. '+A' }
 
   TJSUnaryPlusExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryMinusExpression }
+  { TJSUnaryMinusExpression - e.g. '-A' }
 
   TJSUnaryMinusExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryInvExpression }
+  { TJSUnaryInvExpression - e.g. '~A' }
 
   TJSUnaryInvExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryNotExpression }
+  { TJSUnaryNotExpression - e.g. '!A' }
 
   TJSUnaryNotExpression = Class(TJSUnaryExpression)
+  Public
     Class function PrefixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryPostPlusPlusExpression }
+  { TJSUnaryPostPlusPlusExpression - e.g. 'A++' }
 
   TJSUnaryPostPlusPlusExpression = Class(TJSUnaryExpression)
+  Public
     Class function PostFixOperatorToken : tjsToken; override;
   end;
 
-  { TJSUnaryPostMinusMinusExpression }
+  { TJSUnaryPostMinusMinusExpression - e.g. 'A--' }
 
   TJSUnaryPostMinusMinusExpression = Class(TJSUnaryExpression)
+  Public
     Class function PostFixOperatorToken : tjsToken; override;
   end;
 
 
-
-  { TJSBinary }
+  { TJSBinary - base class }
 
   TJSBinary = Class(TJSElement)
   private
@@ -422,45 +435,52 @@ Type
   end;
   TJSBinaryClass = Class of TJSBinary;
 
-  { TJSStatementList }
+  { TJSStatementList - a list of statements enclosed in curly brackets }
 
   TJSStatementList = Class(TJSBinary); // A->first statement, B->next in list, chained.
-  TJSVariableDeclarationList = Class(TJSBinary);
+
+  { TJSVariableDeclarationList }
+
+  TJSVariableDeclarationList = Class(TJSBinary); // A->first variable, B->next in list, chained.
+
+  { TJSWithStatement }
+
   TJSWithStatement = Class(TJSBinary); // A-> with expression, B->statement(s)
 
-  { TJSBinaryExpression }
+  { TJSBinaryExpression - e.g. A operator B }
 
   TJSBinaryExpression = Class(TJSBinary)
+  Public
     Class function OperatorToken : tjsToken; virtual;
     Class function OperatorString : string;
     Class Function AllowCompact : Boolean; virtual;
   end;
 
-  { TJSLogicalOrExpression }
+  { TJSLogicalOrExpression - e.g. A || B }
 
   TJSLogicalOrExpression = Class (TJSBinaryExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSLogicalAndExpression }
+  { TJSLogicalAndExpression - e.g. A && B }
 
   TJSLogicalAndExpression = Class (TJSBinaryExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSBitwiseAndExpression }
+  { TJSBitwiseAndExpression - e.g. A & B }
 
   TJSBitwiseAndExpression = Class (TJSBinaryExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSBitwiseOrExpression }
+  { TJSBitwiseOrExpression - e.g. A | B }
 
   TJSBitwiseOrExpression = Class (TJSBinaryExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSBitwiseXOrExpression }
+  { TJSBitwiseXOrExpression - e.g. A ^ B }
 
   TJSBitwiseXOrExpression = Class (TJSBinaryExpression)
     Class function OperatorToken : tjsToken; override;
@@ -468,25 +488,25 @@ Type
 
   TJSEqualityExpression = Class (TJSBinaryExpression);
 
-  { TJSEqualityExpressionEQ }
+  { TJSEqualityExpressionEQ - e.g. A == B }
 
   TJSEqualityExpressionEQ = Class(TJSEqualityExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSEqualityExpressionNE }
+  { TJSEqualityExpressionNE - e.g. A != B }
 
   TJSEqualityExpressionNE = Class(TJSEqualityExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSEqualityExpressionSEQ }
+  { TJSEqualityExpressionSEQ strict equal - e.g. A === B }
 
   TJSEqualityExpressionSEQ = Class(TJSEqualityExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSEqualityExpressionSNE }
+  { TJSEqualityExpressionSNE not strict equal - e.g. A !== B }
 
   TJSEqualityExpressionSNE = Class(TJSEqualityExpression)
     Class function OperatorToken : tjsToken; override;
@@ -494,38 +514,38 @@ Type
 
   TJSRelationalExpression = Class(TJSBinaryExpression);
 
-  { TJSRelationalExpressionLT }
+  { TJSRelationalExpressionLT lower than - e.g. A < B }
 
   TJSRelationalExpressionLT = Class(TJSRelationalExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSRelationalExpressionGT }
+  { TJSRelationalExpressionGT greater than - e.g. A > B }
 
   TJSRelationalExpressionGT = Class(TJSRelationalExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSRelationalExpressionLE }
+  { TJSRelationalExpressionLE lower equal - e.g. A <= B }
 
   TJSRelationalExpressionLE = Class(TJSRelationalExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSRelationalExpressionGE }
+  { TJSRelationalExpressionGE greater equal - e.g. A >= B }
 
   TJSRelationalExpressionGE = Class(TJSRelationalExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSRelationalExpressionIn }
+  { TJSRelationalExpressionIn - e.g. A in B }
 
   TJSRelationalExpressionIn = Class(TJSRelationalExpression)
     Class function OperatorToken : tjsToken; override;
     Class Function AllowCompact : Boolean; override;
   end;
 
-  { TJSRelationalExpressionInstanceOf }
+  { TJSRelationalExpressionInstanceOf - e.g. A instanceof B }
 
   TJSRelationalExpressionInstanceOf = Class(TJSRelationalExpression)
     Class function OperatorToken : tjsToken; override;
@@ -534,19 +554,19 @@ Type
 
   TJSShiftExpression = Class(TJSBinaryExpression);
 
-  { TJSLShiftExpression }
+  { TJSLShiftExpression - e.g. A << B }
 
   TJSLShiftExpression = Class(TJSShiftExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSRShiftExpression }
+  { TJSRShiftExpression right shift keep sign - e.g. A >> B }
 
   TJSRShiftExpression = Class(TJSShiftExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSURShiftExpression }
+  { TJSURShiftExpression right shift unsigned, insert zeroes - e.g. A >>> B }
 
   TJSURShiftExpression = Class(TJSShiftExpression)
     Class function OperatorToken : tjsToken; override;
@@ -554,13 +574,13 @@ Type
 
   TJSAdditiveExpression = Class(TJSBinaryExpression);
 
-  { TJSAdditiveExpressionPlus }
+  { TJSAdditiveExpressionPlus - e.g. A + B }
 
   TJSAdditiveExpressionPlus = Class(TJSAdditiveExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSAdditiveExpressionMinus }
+  { TJSAdditiveExpressionMinus - e.g. A - B }
 
   TJSAdditiveExpressionMinus = Class(TJSAdditiveExpression)
     Class function OperatorToken : tjsToken; override;
@@ -568,31 +588,31 @@ Type
 
   TJSMultiplicativeExpression = Class(TJSBinaryExpression);
 
-  { TJSMultiplicativeExpressionMul }
+  { TJSMultiplicativeExpressionMul - e.g. A * B }
 
   TJSMultiplicativeExpressionMul = Class(TJSMultiplicativeExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSMultiplicativeExpressionDiv }
+  { TJSMultiplicativeExpressionDiv - e.g. A / B }
 
   TJSMultiplicativeExpressionDiv = Class(TJSMultiplicativeExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSMultiplicativeExpressionMod }
+  { TJSMultiplicativeExpressionMod - e.g. A % B }
 
   TJSMultiplicativeExpressionMod = Class(TJSMultiplicativeExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSCommaExpression }
+  { TJSCommaExpression - e.g. A , B }
 
   TJSCommaExpression = Class(TJSBinaryExpression)
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSConditionalExpression }
+  { TJSConditionalExpression - e.g. A ? B :C }
 
   TJSConditionalExpression = Class(TJSElement)
   private
@@ -606,7 +626,7 @@ Type
     Property C : TJSElement Read FC Write FC;
   end;
 
-  { TJSAssignStatement }
+  { TJSAssignStatement - e.g. LHS operator Expr }
 
   TJSAssignStatement = Class(TJSElement)
   private
@@ -622,79 +642,91 @@ Type
 
   TJSAssignStatementClass = Class of TJSAssignStatement;
 
-  { TJSSimpleAssignStatement }
+  { TJSSimpleAssignStatement - e.g. LHS=Expr }
 
   TJSSimpleAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSMulEqAssignStatement }
+  { TJSMulEqAssignStatement - e.g. LHS*=Expr }
 
   TJSMulEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSDivEqAssignStatement }
+  { TJSDivEqAssignStatement - e.g. LHS/=Expr }
 
   TJSDivEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSModEqAssignStatement }
+  { TJSModEqAssignStatement - e.g. LHS%=Expr }
 
   TJSModEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSAddEqAssignStatement }
+  { TJSAddEqAssignStatement - e.g. LHS+=Expr }
 
   TJSAddEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSSubEqAssignStatement }
+  { TJSSubEqAssignStatement - e.g. LHS-=Expr }
 
   TJSSubEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSLShiftEqAssignStatement }
+  { TJSLShiftEqAssignStatement - e.g. LHS<<=Expr }
 
   TJSLShiftEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSRShiftEqAssignStatement }
+  { TJSRShiftEqAssignStatement - e.g. LHS>>=Expr keep sign }
 
   TJSRShiftEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSURShiftEqAssignStatement }
+  { TJSURShiftEqAssignStatement - e.g. LHS>>>=Expr unsigned, insert zeroes }
 
   TJSURShiftEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSANDEqAssignStatement }
+  { TJSANDEqAssignStatement - e.g. LHS&=Expr }
 
   TJSANDEqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSOREqAssignStatement }
+  { TJSOREqAssignStatement - e.g. LHS|=Expr }
 
   TJSOREqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSXOREqAssignStatement }
+  { TJSXOREqAssignStatement - e.g. LHS^=Expr }
 
   TJSXOREqAssignStatement = Class(TJSAssignStatement)
+  Public
     Class function OperatorToken : tjsToken; override;
   end;
 
-  { TJSVarDeclaration }
+  { TJSVarDeclaration - e.g. Name=Init }
 
   TJSVarDeclaration = Class(TJSElement)
   private
@@ -706,7 +738,7 @@ Type
     Property Init : TJSElement Read FInit Write FInit;
   end;
 
-  { TJSIfStatement }
+  { TJSIfStatement - e.g. if (Cond) btrue else bfalse }
 
   TJSIfStatement = Class(TJSElement)
   private
@@ -716,13 +748,13 @@ Type
   Public
     Destructor Destroy; override;
     Property Cond : TJSElement Read FCond Write FCond;
-    Property btrue : TJSElement Read FBTrue Write FBTrue;
-    Property bfalse : TJSElement Read FBFalse Write FBFalse;
+    Property BTrue : TJSElement Read FBTrue Write FBTrue;
+    Property BFalse : TJSElement Read FBFalse Write FBFalse;
   end;
 
-  { TJSWhileStatement }
-
-  { TJSTargetStatement }
+  { TJSTargetStatement
+    - base class for statements targetable by continue and break
+    - TargetName can be empty }
 
   TJSTargetStatement = Class(TJSElement)
   private
@@ -733,17 +765,17 @@ Type
     Property TargetName : TJSString Read FTargetName Write FTargetName;
   end;
 
-  { TJSBodyStatement }
+  { TJSBodyStatement - base class }
 
   TJSBodyStatement = Class(TJSTargetStatement)
   private
     FBody: TJSElement;
   Public
     Destructor Destroy; override;
-    Property body : TJSElement Read FBody Write FBody;
+    Property Body : TJSElement Read FBody Write FBody;
   end;
 
-  { TJSCondLoopStatement }
+  { TJSCondLoopStatement - base class for do..while and while..do }
 
   TJSCondLoopStatement = Class(TJSBodyStatement)
   private
@@ -753,10 +785,15 @@ Type
     Property Cond : TJSElement Read FCond Write FCond;
   end;
 
+  { TJSWhileStatement - e.g. 'while(Cond) Body' }
+
   TJSWhileStatement = Class(TJSCondLoopStatement);
+
+  { TJSDoWhileStatement - e.g. 'do Body while(Cond)' }
+
   TJSDoWhileStatement = Class(TJSWhileStatement);
 
-  { TJSForStatement }
+  { TJSForStatement - e.g. 'for(Init;Cond;Incr) Body' }
 
   TJSForStatement = Class(TJSCondLoopStatement)
   private
@@ -768,7 +805,7 @@ Type
     Property Init : TJSElement Read FInit Write FInit;
   end;
 
-  { TJSForInStatement }
+  { TJSForInStatement - e.g. 'for(LHS in List) Body' }
 
   TJSForInStatement = Class(TJSBodyStatement)
   private
@@ -780,11 +817,15 @@ Type
     Property List : TJSElement Read FList Write FList;
   end;
 
+  { TJSContinueStatement - e.g. 'continue'}
+
   TJSContinueStatement = Class(TJSTargetStatement);
 
+  { TJSBreakStatement - e.g. 'break' }
+
   TJSBreakStatement = Class(TJSTargetStatement);
 
-  { TJSReturn }
+  { TJSReturn - e.g. 'return Expr'}
 
   TJSReturnStatement = Class(TJSElement)
   private
@@ -794,7 +835,7 @@ Type
     Property Expr : TJSElement Read FExpr Write FExpr;
   end;
 
-  { TJSCaseElement }
+  { TJSCaseElement - element of TJSCaseElements, e.g. 'case Expr: Body' }
 
   TJSCaseElement = Class(TCollectionItem)
   private
@@ -806,7 +847,7 @@ Type
     Property Body : TJSElement Read FBody Write FBody;
   end;
 
-  { TJSCaseElements }
+  { TJSCaseElements - Cases property of TJSSwitch }
 
   TJSCaseElements = Class(TCollection)
   private
@@ -816,7 +857,7 @@ Type
     Property Cases[AIndex : Integer] : TJSCaseElement Read GetC ;default;
   end;
 
-  { TJSSwitch }
+  { TJSSwitch - e.g. switch(Cond) Cases }
 
   TJSSwitchStatement = Class(TJSTargetStatement)
   private
@@ -828,10 +869,10 @@ Type
     Destructor Destroy; override;
     Property Cond : TJSelement Read FCond Write FCond;
     Property Cases : TJSCaseElements Read FCases;
-    Property TheDefault : TJSCaseelement Read FDefault Write FDefault;
+    Property TheDefault : TJSCaseelement Read FDefault Write FDefault; // one of Cases
   end;
 
-  { TJSLabeledStatement }
+  { TJSLabeledStatement - e.g. 'TheLabel : A' }
 
   TJSLabeledStatement = Class(TJSUnary)
   private
@@ -839,11 +880,11 @@ Type
     FTarget: Integer;
   Public
     Destructor Destroy; override;
-    Property target: Integer Read FTarget Write FTarget;
+    Property Target: Integer Read FTarget Write FTarget;
     Property TheLabel : TJSLabel Read FLabel Write Flabel;
   end;
 
-  { TJSTryStatement }
+  { TJSTryStatement - e.g. 'try Block catch(Ident) BCatch finally BFinally' }
 
   TJSTryStatement = Class(TJSElement)
   private
@@ -864,9 +905,9 @@ Type
   TJSTryFinallyStatement = Class(TJSTryStatement);
 
 
-  { TJSFunction }
+  { TJSFunctionDeclarationStatement - as TJSFuncDef, except as a statement }
 
-  TJSFunctionDeclarationStatement = Class(TJSelement)
+  TJSFunctionDeclarationStatement = Class(TJSElement)
   private
     FFuncDef: TJSFuncDef;
   Public
@@ -874,16 +915,16 @@ Type
     Property AFunction : TJSFuncDef Read FFuncDef Write FFuncDef;
   end;
 
-  { TJSFunctionBody }
+  { TJSFunctionBody - the statement block of a function }
 
   TJSFunctionBody = Class(TJSUnary)
   private
-    FisProgram: Boolean;
+    FIsProgram: Boolean;
   Public
-    Property isProgram : Boolean Read FisProgram Write FIsProgram;
+    Property isProgram : Boolean Read FIsProgram Write FIsProgram;
   end;
 
-  { TJSElementNode }
+  { TJSElementNode - element of TJSElementNodes }
 
   TJSElementNode = Class(TCollectionItem)
   private
@@ -893,7 +934,7 @@ Type
     Property Node : TJSElement Read FNode Write FNode;
   end;
 
-  { TJSElementNodes }
+  { TJSElementNodes - see TJSSourceElements }
 
   TJSElementNodes = Class(TCollection)
   private
@@ -903,7 +944,9 @@ Type
     Property Nodes[AIndex : Integer] : TJSElementNode Read GetN ; default;
   end;
 
-  { TJSSourceElements }
+  { TJSSourceElements - a list of elements, every element ends in semicolon,
+    first Vars, then Functions, finally Statements }
+
   TJSSourceElements = Class(TJSElement)
   private
     FFunctions: TJSElementNodes;
@@ -912,12 +955,11 @@ Type
   Public
     Constructor Create(ALine,ARow : Integer; const ASource : String = ''); override;
     Destructor Destroy; override;
-    Property Statements : TJSElementNodes Read FStatements;
-    Property functions : TJSElementNodes Read FFunctions;
     Property Vars : TJSElementNodes Read FVars;
+    Property Functions : TJSElementNodes Read FFunctions;
+    Property Statements : TJSElementNodes Read FStatements;
   end;
 
-
 implementation
 
 {$IFDEF NOCLASSES}
@@ -1444,7 +1486,7 @@ end;
 
 { TJSElement }
 
-constructor TJSElement.Create(ALine, ARow: Integer; Const ASource: String = '');
+constructor TJSElement.Create(ALine, ARow: Integer; const ASource: String);
 begin
   FLine:=ALine;
   FRow:=ARow;
@@ -1809,7 +1851,6 @@ begin
   Result:=TJSElementNode(Items[Aindex])
 end;
 
-
 function TJSElementNodes.AddNode: TJSElementNode;
 begin
   Result:=TJSElementNode(Add);

+ 176 - 154
packages/fcl-js/src/jswriter.pp

@@ -127,7 +127,7 @@ Type
     Procedure WriteWithStatement(El: TJSWithStatement);virtual;
     Procedure WriteVarDeclarationList(El: TJSVariableDeclarationList);virtual;
     Procedure WriteConditionalExpression(El: TJSConditionalExpression);virtual;
-    Procedure WriteFunctionBody(el: TJSFunctionBody);virtual;
+    Procedure WriteFunctionBody(El: TJSFunctionBody);virtual;
     Procedure WriteFunctionDeclarationStatement(El: TJSFunctionDeclarationStatement);virtual;
     Procedure WriteLabeledStatement(El: TJSLabeledStatement);virtual;
     Procedure WriteReturnStatement(EL: TJSReturnStatement);virtual;
@@ -136,7 +136,8 @@ Type
     Procedure WritePrimaryExpression(El: TJSPrimaryExpression);virtual;
     Procedure WriteBinary(El: TJSBinary);virtual;
   Public
-    Class Function EscapeString(const S: TJSString): TJSString;
+    Function EscapeString(const S: TJSString): String;
+    Function JSStringToStr(const S: TJSString): string;
     Constructor Create(AWriter : TTextWriter);
     Constructor Create(Const AFileName : String);
     Destructor Destroy; override;
@@ -144,7 +145,7 @@ Type
     Procedure Indent;
     Procedure Undent;
     Property Writer : TTextWriter Read FWriter;
-    Property options : TWriteOptions Read FOptions Write SetOptions;
+    Property Options : TWriteOptions Read FOptions Write SetOptions;
     Property IndentSize : Byte Read FIndentSize Write FIndentSize;
     Property UseUTF8 : Boolean Read GetUseUTF8;
   end;
@@ -275,29 +276,29 @@ begin
   Result:=(woUseUTF8 in Options)
 end;
 
-Procedure TJSWriter.Error(Const Msg: String);
+procedure TJSWriter.Error(const Msg: String);
 begin
   Raise EJSWriter.Create(Msg);
 end;
 
-Procedure TJSWriter.Error(Const Fmt: String; Args: Array of const);
+procedure TJSWriter.Error(const Fmt: String; Args: array of const);
 begin
   Raise EJSWriter.CreateFmt(Fmt,Args);
 end;
 
-Procedure TJSWriter.WriteIndent;
+procedure TJSWriter.WriteIndent;
 
 begin
   If (FLinePos=0) then
     FLinePos:=Writer.Write(StringOfChar(FIndentChar,FCurIndent));
 end;
 
-Procedure TJSWriter.Indent;
+procedure TJSWriter.Indent;
 begin
   Inc(FCurIndent,FIndentSIze);
 end;
 
-Procedure TJSWriter.Undent;
+procedure TJSWriter.Undent;
 begin
   if (FCurIndent>=FIndentSIze) then
     Dec(FCurIndent,FIndentSIze)
@@ -305,7 +306,7 @@ begin
     FCurIndent:=0;
 end;
 
-Procedure TJSWriter.Write(Const U: UnicodeString);
+procedure TJSWriter.Write(const U: UnicodeString);
 
 Var
   S : UTF8String;
@@ -321,7 +322,7 @@ begin
     FLinePos:=FLinePos+Writer.Write(U);
 end;
 
-Procedure TJSWriter.Write(Const S: AnsiString);
+procedure TJSWriter.Write(const S: AnsiString);
 begin
   if Not (woUseUTF8 in Options) then
     Write(UnicodeString(S))
@@ -332,7 +333,7 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteLn(Const S: AnsiString);
+procedure TJSWriter.WriteLn(const S: AnsiString);
 begin
   if Not (woUseUTF8 in Options) then
     Writeln(UnicodeString(S))
@@ -344,7 +345,7 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteLn(Const U: UnicodeString);
+procedure TJSWriter.WriteLn(const U: UnicodeString);
 Var
   S : UTF8String;
 
@@ -362,7 +363,7 @@ begin
     end;
 end;
 
-Class Function TJSWriter.EscapeString(const S : TJSString) : TJSString;
+function TJSWriter.EscapeString(const S: TJSString): String;
 
 Var
   I,J,L : Integer;
@@ -376,9 +377,9 @@ begin
   P:=PWideChar(S);
   While I<=L do
     begin
-    if (AnsiChar(P^) in ['"','/','\',#8,#9,#10,#12,#13]) then
+    if (P^ in ['"','/','\',#8,#9,#10,#12,#13]) then
       begin
-      Result:=Result+Copy(S,J,I-J);
+      Result:=Result+JSStringToStr(Copy(S,J,I-J));
       Case P^ of
         '\' : Result:=Result+'\\';
         '/' : Result:=Result+'\/';
@@ -394,10 +395,18 @@ begin
     Inc(I);
     Inc(P);
     end;
-  Result:=Result+Copy(S,J,I-1);
+  Result:=Result+JSStringToStr(Copy(S,J,I-1));
 end;
 
-Procedure TJSWriter.WriteValue(V: TJSValue);
+function TJSWriter.JSStringToStr(const S: TJSString): string;
+begin
+  if UseUTF8 then
+    Result:=UTF8Encode(S)
+  else
+    Result:=String(S);
+end;
+
+procedure TJSWriter.WriteValue(V: TJSValue);
 
 Var
   S : String;
@@ -419,20 +428,20 @@ begin
   Write(S);
 end;
 
-Constructor TJSWriter.Create(AWriter: TTextWriter);
+constructor TJSWriter.Create(AWriter: TTextWriter);
 begin
   FWriter:=AWriter;
   FIndentChar:=' ';
   FOptions:=[woUseUTF8];
 end;
 
-Constructor TJSWriter.Create(Const AFileName: String);
+constructor TJSWriter.Create(const AFileName: String);
 begin
   Create(TFileWriter.Create(AFileName));
   FFreeWriter:=True;
 end;
 
-Destructor TJSWriter.Destroy;
+destructor TJSWriter.Destroy;
 begin
   If FFreeWriter then
     begin
@@ -442,7 +451,7 @@ begin
   inherited Destroy;
 end;
 
-Procedure TJSWriter.WriteFuncDef(FD: TJSFuncDef);
+procedure TJSWriter.WriteFuncDef(FD: TJSFuncDef);
 
 Var
   C : Boolean;
@@ -471,7 +480,10 @@ begin
     begin
     FSkipBrackets:=True;
     WriteJS(FD.Body);
-    If not (FD.Body.A is TJSStatementList) then
+    If (Assigned(FD.Body.A))
+    and (not (FD.Body.A is TJSStatementList))
+    and (not (FD.Body.A is TJSSourceElements))
+    then
       if C then
         Write('; ')
       else
@@ -482,12 +494,13 @@ begin
   else
     begin
     undent;
-    Writeln('}');
+    Write('}'); // do not writeln
     end;
 end;
 
-Procedure TJSWriter.WriteEmptyBlockStatement(El: TJSEmptyBlockStatement);
+procedure TJSWriter.WriteEmptyBlockStatement(El: TJSEmptyBlockStatement);
 begin
+  if El=nil then ;
   if woCompact in Options then
     Write('{}')
   else
@@ -497,37 +510,39 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteEmptyStatement(El: TJSEmptyStatement);
+procedure TJSWriter.WriteEmptyStatement(El: TJSEmptyStatement);
 begin
-  if woEmptyStatementAsComment in options then
+  if El=nil then ;
+  if woEmptyStatementAsComment in Options then
     Write('/* Empty statement */')
 end;
 
-Procedure TJSWriter.WriteRegularExpressionLiteral(El: TJSRegularExpressionLiteral);
+procedure TJSWriter.WriteRegularExpressionLiteral(
+  El: TJSRegularExpressionLiteral);
 
 begin
   Write('/');
-  Write(EscapeString(EL.Pattern.AsString));
+  Write(EscapeString(El.Pattern.AsString));
   Write('/');
-  If Assigned(EL.PatternFlags) then
-    Write(EscapeString(EL.PatternFlags.AsString));
+  If Assigned(El.PatternFlags) then
+    Write(EscapeString(El.PatternFlags.AsString));
 end;
 
-Procedure TJSWriter.WriteLiteral(El: TJSLiteral);
+procedure TJSWriter.WriteLiteral(El: TJSLiteral);
 begin
   WriteValue(el.Value);
 end;
 
-Procedure TJSWriter.WritePrimaryExpression(El: TJSPrimaryExpression);
+procedure TJSWriter.WritePrimaryExpression(El: TJSPrimaryExpression);
 
 begin
   if El is TJSPrimaryExpressionThis then
     Write('this')
-  else if el is TJSPrimaryExpressionIdent then
+  else if El is TJSPrimaryExpressionIdent then
     Write(TJSPrimaryExpressionIdent(El).Name);
 end;
 
-Procedure TJSWriter.WriteArrayLiteral(El : TJSArrayLiteral);
+procedure TJSWriter.WriteArrayLiteral(El: TJSArrayLiteral);
 
 
 
@@ -576,7 +591,7 @@ begin
 end;
 
 
-Procedure TJSWriter.WriteObjectLiteral(El : TJSObjectLiteral);
+procedure TJSWriter.WriteObjectLiteral(El: TJSObjectLiteral);
 
 
 Var
@@ -620,15 +635,12 @@ begin
   Write('}');
 end;
 
-Procedure TJSWriter.WriteMemberExpression(el : TJSMemberExpression);
+procedure TJSWriter.WriteMemberExpression(el: TJSMemberExpression);
 
-Var
-  I : integer;
-  A : TJSArguments;
 begin
   if el is TJSNewMemberExpression then
     Write('new ');
-  WriteJS(el.mexpr);
+  WriteJS(el.MExpr);
   if el is TJSDotMemberExpression then
     begin
     write('.');
@@ -649,11 +661,8 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteCallExpression(El : TJSCallExpression);
+procedure TJSWriter.WriteCallExpression(El: TJSCallExpression);
 
-Var
-  I : integer;
-  A : TJSArguments;
 begin
   WriteJS(El.Expr);
   if Assigned(El.Args) then
@@ -662,7 +671,7 @@ begin
     Write('()');
 end;
 
-Procedure TJSWriter.WriteUnary(El : TJSUnary);
+procedure TJSWriter.WriteUnary(El: TJSUnary);
 
 Var
   S : String;
@@ -680,11 +689,12 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteStatementList(El : TJSStatementList);
+procedure TJSWriter.WriteStatementList(El: TJSStatementList);
 
 Var
   C : Boolean;
   B : Boolean;
+  LastEl: TJSElement;
 
 begin
   C:=(woCompact in Options);
@@ -694,19 +704,25 @@ begin
     Write('{');
     if not C then writeln('');
     end;
-  if Assigned(EL.A) then
+  if Assigned(El.A) then
     begin
-    WriteJS(EL.A);
-    if Assigned(EL.B) then
+    WriteJS(El.A);
+    LastEl:=El.A;
+    if Assigned(El.B) then
       begin
-      if C then
-        Write('; ')
-      else
-        Writeln(';');
+      if not (LastEl is TJSStatementList) then
+        begin
+        if C then
+          Write('; ')
+        else
+          Writeln(';');
+        end;
       FSkipBrackets:=True;
-      WriteJS(EL.B);
+      WriteJS(El.B);
+      LastEl:=El.B;
       end;
-    if not C then writeln(';');
+    if (not C) and not (LastEl is TJSStatementList) then
+      writeln(';');
     end;
   if B then
     begin
@@ -715,7 +731,7 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteWithStatement(El : TJSWithStatement);
+procedure TJSWriter.WriteWithStatement(El: TJSWithStatement);
 begin
    Write('with (');
    WriteJS(EL.A);
@@ -728,7 +744,7 @@ begin
    Undent;
 end;
 
-Procedure TJSWriter.WriteVarDeclarationList(El : TJSVariableDeclarationList);
+procedure TJSWriter.WriteVarDeclarationList(El: TJSVariableDeclarationList);
 
 begin
   WriteJS(EL.A);
@@ -739,30 +755,28 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteBinary(El : TJSBinary);
+procedure TJSWriter.WriteBinary(El: TJSBinary);
 
 Var
   S : AnsiString;
-  B : Boolean;
-  T : TJSToken;
-
+  AllowCompact : Boolean;
 begin
   Write('(');
   WriteJS(EL.A);
-  B:=False;
+  AllowCompact:=False;
   if (el is TJSBinaryExpression) then
     begin
     S:=TJSBinaryExpression(El).OperatorString;
-    B:=TJSBinaryExpression(El).AllowCompact;
+    AllowCompact:=TJSBinaryExpression(El).AllowCompact;
     end;
-  If Not (B and (woCompact in Options)) then
+  If Not (AllowCompact and (woCompact in Options)) then
     S:=' '+S+' ';
-  Write(s);
+  Write(S);
   WriteJS(EL.B);
   Write(')');
 end;
 
-Procedure TJSWriter.WriteConditionalExpression(El : TJSConditionalExpression);
+procedure TJSWriter.WriteConditionalExpression(El: TJSConditionalExpression);
 
 begin
   write('(');
@@ -774,11 +788,10 @@ begin
   write(')');
 end;
 
-Procedure TJSWriter.WriteAssignStatement(El : TJSAssignStatement);
+procedure TJSWriter.WriteAssignStatement(El: TJSAssignStatement);
 
 Var
   S : AnsiString;
-  T : TJSToken;
 begin
   WriteJS(EL.LHS);
   S:=El.OperatorString;
@@ -788,7 +801,7 @@ begin
   WriteJS(EL.Expr);
 end;
 
-Procedure TJSWriter.WriteVarDeclaration(El : TJSVarDeclaration);
+procedure TJSWriter.WriteVarDeclaration(El: TJSVarDeclaration);
 
 begin
   Write(EL.Name);
@@ -799,7 +812,7 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteIfStatement(El : TJSIfStatement);
+procedure TJSWriter.WriteIfStatement(El: TJSIfStatement);
 
 begin
   Write('if (');
@@ -813,7 +826,7 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteForInStatement(El : TJSForInStatement);
+procedure TJSWriter.WriteForInStatement(El: TJSForInStatement);
 
 begin
   Write('for (');
@@ -823,11 +836,11 @@ begin
   if Assigned(El.List) then
     WriteJS(El.List);
   Write(') ');
-  if Assigned(El.body) then
+  if Assigned(El.Body) then
     WriteJS(El.Body);
 end;
 
-Procedure TJSWriter.WriteForStatement(El : TJSForStatement);
+procedure TJSWriter.WriteForStatement(El: TJSForStatement);
 
 begin
   Write('for (');
@@ -840,18 +853,18 @@ begin
   if Assigned(El.Incr) then
     WriteJS(El.Incr);
   Write(') ');
-  if Assigned(El.body) then
+  if Assigned(El.Body) then
     WriteJS(El.Body);
 end;
 
-Procedure TJSWriter.WriteWhileStatement(El : TJSWhileStatement);
+procedure TJSWriter.WriteWhileStatement(El: TJSWhileStatement);
 
 
 begin
   if El is TJSDoWhileStatement then
     begin
     Write('do ');
-    if Assigned(El.body) then
+    if Assigned(El.Body) then
       WriteJS(El.Body);
     Write(' while (');
     If Assigned(El.Cond) then
@@ -864,12 +877,12 @@ begin
     If Assigned(El.Cond) then
       WriteJS(EL.Cond);
     Write(') ');
-    if Assigned(El.body) then
+    if Assigned(El.Body) then
       WriteJS(El.Body);
     end;
 end;
 
-Procedure TJSWriter.WriteSwitchStatement(El : TJSSwitchStatement);
+procedure TJSWriter.WriteSwitchStatement(El: TJSSwitchStatement);
 
 Var
   C : Boolean;
@@ -922,7 +935,7 @@ begin
   Write('}');
 end;
 
-Procedure TJSWriter.WriteTargetStatement(El : TJSTargetStatement);
+procedure TJSWriter.WriteTargetStatement(El: TJSTargetStatement);
 
 Var
   TN : TJSString;
@@ -955,14 +968,14 @@ begin
     Error('Unknown target statement class: "%s"',[EL.ClassName])
 end;
 
-Procedure TJSWriter.WriteReturnStatement(EL: TJSReturnStatement);
+procedure TJSWriter.WriteReturnStatement(EL: TJSReturnStatement);
 
 begin
   Write('return ');
   WriteJS(EL.Expr);
 end;
 
-Procedure TJSWriter.WriteLabeledStatement(El : TJSLabeledStatement);
+procedure TJSWriter.WriteLabeledStatement(El: TJSLabeledStatement);
 begin
   if Assigned(EL.TheLabel) then
     begin
@@ -976,7 +989,7 @@ begin
   WriteJS(EL.A);
 end;
 
-Procedure TJSWriter.WriteTryStatement(el :TJSTryStatement);
+procedure TJSWriter.WriteTryStatement(el: TJSTryStatement);
 
 Var
   C : Boolean;
@@ -1036,52 +1049,61 @@ begin
     end;
 end;
 
-Procedure TJSWriter.WriteFunctionBody(el : TJSFunctionBody);
+procedure TJSWriter.WriteFunctionBody(El: TJSFunctionBody);
 
 begin
-  if Assigned(EL.A) then
-    WriteJS(EL.A);
+  if Assigned(El.A) then
+    WriteJS(El.A);
 end;
 
-Procedure TJSWriter.WriteFunctionDeclarationStatement(El : TJSFunctionDeclarationStatement);
+procedure TJSWriter.WriteFunctionDeclarationStatement(
+  El: TJSFunctionDeclarationStatement);
 
 begin
   if Assigned(EL.AFunction) then
     WriteFuncDef(EL.AFunction);
 end;
 
-Procedure TJSWriter.WriteSourceElements(El :TJSSourceElements);
+procedure TJSWriter.WriteSourceElements(El: TJSSourceElements);
 
 Var
-  I : Integer;
   C : Boolean;
-  E : TJSElement;
+
+  Procedure WriteElements(Elements: TJSElementNodes);
+  Var
+    I : Integer;
+    E : TJSElement;
+  begin
+    if Elements=nil then exit;
+    For I:=0 to Elements.Count-1 do
+      begin
+      E:=Elements.Nodes[i].Node;
+      WriteJS(E);
+      if Not C then
+        WriteLn(';')
+      else
+        if I<Elements.Count-1 then
+          Write('; ')
+        else
+          Write(';')
+      end;
+  end;
 
 begin
   C:=(woCompact in Options);
-  For I:=0 to EL.Statements.Count-1 do
-    begin
-    E:=EL.Statements.Nodes[i].Node;
-    WriteJS(E);
-    if Not C then
-      WriteLn(';')
-    else
-      if I<EL.Statements.Count-1 then
-        Write('; ')
-      else
-        Write(';')
-    end;
+  WriteElements(El.Vars);
+  WriteElements(El.Functions);
+  WriteElements(El.Statements);
 end;
 
-
-Procedure TJSWriter.WriteVariableStatement(el : TJSVariableStatement);
+procedure TJSWriter.WriteVariableStatement(el: TJSVariableStatement);
 
 begin
   Write('var ');
   WriteJS(EL.A);
 end;
 
-Procedure TJSWriter.WriteJS(El: TJSElement);
+procedure TJSWriter.WriteJS(El: TJSElement);
 begin
 {$IFDEF DEBUGJSWRITER}
   if (EL<>Nil) then
@@ -1090,62 +1112,62 @@ begin
     system.Writeln('WriteJS : El = Nil');
 {$ENDIF}
   if (El is TJSEmptyBlockStatement ) then
-    WriteEmptyBlockStatement(TJSEmptyBlockStatement(el))
+    WriteEmptyBlockStatement(TJSEmptyBlockStatement(El))
   else if (El is TJSEmptyStatement) then
-    WriteEmptyStatement(TJSEmptyStatement(el))
-  else if (el is TJSLiteral) then
-    WriteLiteral(TJSLiteral(el))
-  else if (el is TJSPrimaryExpression) then
-    WritePrimaryExpression(TJSPrimaryExpression(el))
-  else if (el is TJSArrayLiteral) then
-    WriteArrayLiteral(TJSArrayLiteral(el))
-  else if (el is TJSObjectLiteral) then
-    WriteObjectLiteral(TJSObjectLiteral(el))
-  else if (el is TJSMemberExpression) then
-    WriteMemberExpression(TJSMemberExpression(el))
-  else if (el is TJSRegularExpressionLiteral) then
+    WriteEmptyStatement(TJSEmptyStatement(El))
+  else if (El is TJSLiteral) then
+    WriteLiteral(TJSLiteral(El))
+  else if (El is TJSPrimaryExpression) then
+    WritePrimaryExpression(TJSPrimaryExpression(El))
+  else if (El is TJSArrayLiteral) then
+    WriteArrayLiteral(TJSArrayLiteral(El))
+  else if (El is TJSObjectLiteral) then
+    WriteObjectLiteral(TJSObjectLiteral(El))
+  else if (El is TJSMemberExpression) then
+    WriteMemberExpression(TJSMemberExpression(El))
+  else if (El is TJSRegularExpressionLiteral) then
     WriteRegularExpressionLiteral(TJSRegularExpressionLiteral(El))
-  else if (el is TJSCallExpression) then
-    WriteCallExpression(TJSCallExpression(el))
-  else if (el is TJSLabeledStatement) then // Before unary
-    WriteLabeledStatement(TJSLabeledStatement(el))
-  else if (el is TJSFunctionBody) then // Before unary
-    WriteFunctionBody(TJSFunctionBody(el))
-  else if (el is TJSVariableStatement) then // Before unary
-    WriteVariableStatement(TJSVariableStatement(el))
-  else if (el is TJSUNary) then
-    WriteUnary(TJSUnary(el))
-  else if (el is TJSVariableDeclarationList) then
-    WriteVarDeclarationList(TJSVariableDeclarationList(el)) // Must be before binary
-  else if (el is TJSStatementList) then
-    WriteStatementList(TJSStatementList(el)) // Must be before binary
-  else if (el is TJSWithStatement) then
+  else if (El is TJSCallExpression) then
+    WriteCallExpression(TJSCallExpression(El))
+  else if (El is TJSLabeledStatement) then // Before unary
+    WriteLabeledStatement(TJSLabeledStatement(El))
+  else if (El is TJSFunctionBody) then // Before unary
+    WriteFunctionBody(TJSFunctionBody(El))
+  else if (El is TJSVariableStatement) then // Before unary
+    WriteVariableStatement(TJSVariableStatement(El))
+  else if (El is TJSUNary) then
+    WriteUnary(TJSUnary(El))
+  else if (El is TJSVariableDeclarationList) then
+    WriteVarDeclarationList(TJSVariableDeclarationList(El)) // Must be before binary
+  else if (El is TJSStatementList) then
+    WriteStatementList(TJSStatementList(El)) // Must be before binary
+  else if (El is TJSWithStatement) then
     WriteWithStatement(TJSWithStatement(El)) // Must be before binary
-  else if (el is TJSBinary) then
-    WriteBinary(TJSBinary(el))
-  else if (el is TJSConditionalExpression) then
-    WriteConditionalExpression(TJSConditionalExpression(el))
-  else if (el is TJSAssignStatement) then
-    WriteAssignStatement(TJSAssignStatement(el))
-  else if (el is TJSVarDeclaration) then
-    WriteVarDeclaration(TJSVarDeclaration(el))
-  else if (el is TJSIfStatement) then
-    WriteIfStatement(TJSIfStatement(el))
-  else if (el is TJSTargetStatement) then
-    WriteTargetStatement(TJSTargetStatement(el))
-  else if (el is TJSReturnStatement) then
-    WriteReturnStatement(TJSReturnStatement(el))
-  else if (el is TJSTryStatement) then
-    WriteTryStatement(TJSTryStatement(el))
-  else if (el is TJSFunctionDeclarationStatement) then
-    WriteFunctionDeclarationStatement(TJSFunctionDeclarationStatement(el))
-  else if (el is TJSSourceElements) then
-    WriteSourceElements(TJSSourceElements(el))
-  else if EL=Nil then
+  else if (El is TJSBinary) then
+    WriteBinary(TJSBinary(El))
+  else if (El is TJSConditionalExpression) then
+    WriteConditionalExpression(TJSConditionalExpression(El))
+  else if (El is TJSAssignStatement) then
+    WriteAssignStatement(TJSAssignStatement(El))
+  else if (El is TJSVarDeclaration) then
+    WriteVarDeclaration(TJSVarDeclaration(El))
+  else if (El is TJSIfStatement) then
+    WriteIfStatement(TJSIfStatement(El))
+  else if (El is TJSTargetStatement) then
+    WriteTargetStatement(TJSTargetStatement(El))
+  else if (El is TJSReturnStatement) then
+    WriteReturnStatement(TJSReturnStatement(El))
+  else if (El is TJSTryStatement) then
+    WriteTryStatement(TJSTryStatement(El))
+  else if (El is TJSFunctionDeclarationStatement) then
+    WriteFunctionDeclarationStatement(TJSFunctionDeclarationStatement(El))
+  else if (El is TJSSourceElements) then
+    WriteSourceElements(TJSSourceElements(El))
+  else if El=Nil then
     Error(SErrNilNode)
   else
     Error(SErrUnknownJSClass,[El.ClassName]);
-//  Write('/* '+EL.ClassName+' */');
+//  Write('/* '+El.ClassName+' */');
   FSkipBrackets:=False;
 end;
 

+ 6 - 14
packages/fcl-js/tests/tcwriter.pp

@@ -5,7 +5,7 @@ unit tcwriter;
 interface
 
 uses
-  Classes, SysUtils, fpcunit, testutils, testregistry, jsbase, jstree, jswriter;
+  Classes, SysUtils, fpcunit, testregistry, jsbase, jstree, jswriter;
 
 type
 
@@ -801,8 +801,6 @@ Procedure TTestStatementWriter.TestVarDeclaration;
 
 Var
   V : TJSVarDeclaration;
-  L : TJSPrimaryExpressionIdent;
-
 begin
   V:=TJSVarDeclaration.Create(0,0);
   V.Name:='a';
@@ -812,8 +810,6 @@ end;
 Procedure TTestStatementWriter.TestVarDeclarationInit;
 Var
   V : TJSVarDeclaration;
-  L : TJSLiteral;
-
 begin
   V:=TJSVarDeclaration.Create(0,0);
   V.Name:='a';
@@ -864,8 +860,6 @@ Procedure TTestStatementWriter.TestVarDeclarationStatement;
 Var
   S : TJSVariableStatement;
   V : TJSVarDeclaration;
-  L : TJSPrimaryExpressionIdent;
-
 begin
   S:=TJSVariableStatement.Create(0,0);
   V:=TJSVarDeclaration.Create(0,0);
@@ -1131,7 +1125,6 @@ Var
   S : TJSForStatement;
   UPP : TJSUnaryPostPlusPlusExpression;
   CL : TJSRelationalExpressionLT;
-  L : TJSLiteral;
   sa : TJSSimpleAssignStatement;
 
 begin
@@ -1156,7 +1149,6 @@ Var
   S : TJSForStatement;
   UPP : TJSUnaryPostPlusPlusExpression;
   CL : TJSRelationalExpressionLT;
-  L : TJSLiteral;
   sa : TJSSimpleAssignStatement;
 
 begin
@@ -1476,7 +1468,7 @@ begin
   FD:=TJSFunctionDeclarationStatement.Create(0,0);
   FD.AFunction:=TJSFuncDef.Create;
   FD.AFunction.Name:='a';
-  AssertWrite('Empty function','function a() {'+sLineBreak+'}'+sLineBreak,FD);
+  AssertWrite('Empty function','function a() {'+sLineBreak+'}',FD);
 end;
 
 Procedure TTestStatementWriter.TestEmptyFunctionDefCompact;
@@ -1505,7 +1497,7 @@ begin
   FD.AFunction.Params.Add('c');
   FD.AFunction.Params.Add('d');
 
-  AssertWrite('Empty function, 3 params','function a(b, c, d) {'+sLineBreak+'}'+sLineBreak,FD);
+  AssertWrite('Empty function, 3 params','function a(b, c, d) {'+sLineBreak+'}',FD);
 end;
 
 Procedure TTestStatementWriter.TestFunctionDefParamsCompact;
@@ -1540,7 +1532,7 @@ begin
   R:=TJSReturnStatement.Create(0,0);
   R.Expr:=CreateLiteral(0);
   FD.AFunction.Body.A:=R;
-  AssertWrite('1 statement, ','function a() {'+sLineBreak+'  return 0;'+sLineBreak+'}'+sLineBreak,FD);
+  AssertWrite('1 statement, ','function a() {'+sLineBreak+'  return 0;'+sLineBreak+'}',FD);
 end;
 
 Procedure TTestStatementWriter.TestFunctionDefBody1Compact;
@@ -1589,7 +1581,7 @@ begin
   L.A:=A;
   L.B:=R;
   FD.AFunction.Body.A:=L;
-  AssertWrite('Function, 2 statements','function a(b) {'+sLineBreak+'  b = (b * 10);'+sLineBreak+'  return b;'+sLineBreak+'}'+sLineBreak,FD);
+  AssertWrite('Function, 2 statements','function a(b) {'+sLineBreak+'  b = (b * 10);'+sLineBreak+'  return b;'+sLineBreak+'}',FD);
 end;
 
 Procedure TTestStatementWriter.TestFunctionDefBody2Compact;
@@ -2400,7 +2392,7 @@ end;
 Function TTestJSWriter.CreateIdent(Const AName: String): TJSPrimaryExpressionIdent;
 begin
   Result:=TJSPrimaryExpressionIdent.Create(0,0);
-  Result.Name:=AName;
+  Result.Name:=TJSString(AName);
 end;
 
 Function TTestJSWriter.CreateLiteral(Const AValue: TJSString): TJSLiteral;

+ 1 - 1
packages/fcl-js/tests/testjs.lpr

@@ -4,7 +4,7 @@ program testjs;
 
 uses
   cwstring,Classes, consoletestrunner, tcscanner, jsparser, jsscanner, jstree, jsbase,
-  tcparser, jswriter, tctextwriter, tcwriter, jstoken;
+  tcparser, jswriter, tcwriter, jstoken;
 
 var
   Application: TTestRunner;

+ 43 - 27
packages/fcl-json/src/jsonconf.pp

@@ -68,6 +68,8 @@ type
   protected
     FJSON: TJSONObject;
     FModified: Boolean;
+    Procedure LoadFromFile(Const AFileName : String);
+    Procedure LoadFromStream(S : TStream); virtual;
     procedure Loaded; override;
     function FindPath(Const APath: UnicodeString; AllowCreate : Boolean) : TJSONObject;
     function FindObject(Const APath: UnicodeString; AllowCreate : Boolean) : TJSONObject;
@@ -673,11 +675,6 @@ end;
 
 procedure TJSONConfig.DoSetFilename(const AFilename: String; ForceReload: Boolean);
 
-Var
-  P : TJSONParser;
-  J : TJSONData;
-  F : TFileStream;
-  
 begin
   if (not ForceReload) and (FFilename = AFilename) then
     exit;
@@ -685,32 +682,11 @@ begin
 
   if csLoading in ComponentState then
     exit;
-
   Flush;
   If Not FileExists(AFileName) then
     Clear
   else
-    begin
-    F:=TFileStream.Create(AFileName,fmopenRead);
-    try
-      P:=TJSONParser.Create(F,FJSONOptions);
-      try
-        J:=P.Parse;
-        If (J is TJSONObject) then
-          begin
-          FreeAndNil(FJSON);
-          FJSON:=J as TJSONObject;
-          FKey:=FJSON;
-          end
-        else
-          Raise EJSONConfigError.CreateFmt(SErrInvalidJSONFile,[AFileName]);
-      finally
-        P.Free;
-      end;
-    finally
-      F.Free;
-    end;
-    end;
+    LoadFromFile(AFileName);
 end;
 
 procedure TJSONConfig.SetFilename(const AFilename: String);
@@ -741,6 +717,46 @@ begin
     Result:=P;
 end;
 
+procedure TJSONConfig.LoadFromFile(const AFileName: String);
+
+Var
+  F : TFileStream;
+
+begin
+  F:=TFileStream.Create(AFileName,fmopenRead);
+  try
+    LoadFromStream(F);
+  finally
+    F.Free;
+  end;
+end;
+
+procedure TJSONConfig.LoadFromStream(S: TStream);
+
+Var
+  P : TJSONParser;
+  J : TJSONData;
+
+begin
+  P:=TJSONParser.Create(S,FJSONOptions);
+  try
+    J:=P.Parse;
+    If (J is TJSONObject) then
+      begin
+      FreeAndNil(FJSON);
+      FJSON:=J as TJSONObject;
+      FKey:=FJSON;
+      end
+    else
+      begin
+      FreeAndNil(J);
+      Raise EJSONConfigError.CreateFmt(SErrInvalidJSONFile,[FileName]);
+      end;
+  finally
+    P.Free;
+  end;
+end;
+
 
 procedure TJSONConfig.CloseKey;
 begin

+ 0 - 1
packages/fcl-json/src/jsonscanner.pp

@@ -62,7 +62,6 @@ Type
 
   TJSONScanner = class
   private
-    FAllowComments: Boolean;
     FSource : TStringList;
     FCurRow: Integer;
     FCurToken: TJSONToken;

+ 14 - 15
packages/fcl-web/src/base/fpoauth2ini.pp

@@ -1,16 +1,3 @@
-{ **********************************************************************
-  This file is part of the Free Component Library (FCL)
-  Copyright (c) 2015 by the Free Pascal development team
-        
-  OAuth2 store using an .ini file.
-            
-  See the file COPYING.FPC, included in this distribution,
-  for details about the copyright.
-                   
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-  **********************************************************************}
 unit fpoauth2ini;
 
 {$mode objfpc}{$H+}
@@ -34,13 +21,13 @@ Type
     FUserSection: String;
     procedure EnsureFileName;
     Procedure EnsureConfigSections;
+    procedure SetSessionSectionUser(AUser: String);
   Protected
     Function DetectSessionFileName : String;
     Function EnsureUserSession(ASession: TOAuth2Session): Boolean; virtual;
   Public
     Constructor Create(AOwner : TComponent); override;
     Destructor Destroy; override;
-
     Procedure SaveConfigToIni(AIni : TCustomIniFile;AConfig : TOAuth2Config); virtual;
     Procedure LoadConfigFromIni(AIni : TCustomIniFile;AConfig : TOAuth2Config); virtual;
     Procedure SaveSessionToIni(AIni : TCustomIniFile;ASession : TOAuth2Session); virtual;
@@ -269,6 +256,17 @@ begin
   inherited Destroy;
 end;
 
+procedure TFPOAuth2IniStore.SetSessionSectionUser(AUser : String);
+
+begin
+  If (UserSessionSection='') then
+    begin
+    if (AUser='') then
+       AUser:='anonymous';
+    UserSessionSection:='session_'+AUser;
+    end;
+end;
+
 procedure TFPOAuth2IniStore.LoadSession(ASession: TOAuth2Session;
   const AUser: String);
 
@@ -276,8 +274,8 @@ Var
   Ini : TMemIniFile;
 
 begin
-  Touch('loadsession');
   EnsureFileName;
+  SetSessionSectionUser(AUser);
   If not EnsureUserSession(ASession) then
     Exit;
   Ini:=TMemIniFile.Create(SessionFileName);
@@ -296,6 +294,7 @@ Var
 
 begin
   EnsureFileName;
+  SetSessionSectionUser(AUser);
   If not EnsureUserSession(ASession) then
     Exit;
   Ini:=TMemIniFile.Create(SessionFileName);

File diff suppressed because it is too large
+ 366 - 201
packages/pastojs/src/fppas2js.pp


+ 45 - 22
packages/pastojs/tests/tcconverter.pp

@@ -11,7 +11,11 @@
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
- **********************************************************************}
+ **********************************************************************
+
+ Examples:
+    ./testpas2js --suite=TTestExpressionConverter.TestVariable
+}
 unit tcconverter;
 
 {$mode objfpc}{$H+}
@@ -19,7 +23,7 @@ unit tcconverter;
 interface
 
 uses
-  Classes, SysUtils, fpcunit, testutils, testregistry, fppas2js, jsbase, jstree, pastree;
+  Classes, SysUtils, fpcunit, testregistry, fppas2js, jsbase, jstree, pastree;
 
 type
 
@@ -102,6 +106,7 @@ type
     Procedure TestMemberExpressionArrayTwoDim;
     Procedure TestVariable;
     Procedure TestArrayVariable;
+    procedure TestClassDecleration;
   end;
 
   { TTestStatementConverter }
@@ -574,12 +579,12 @@ begin
   F:=T.AddExcept;
   F.AddElement(CreateAssignStatement('b','c'));
   El:=TJSTryFinallyStatement(Convert(T,TJSTryCatchStatement));
-  L:=AssertListStatement('try..except block is statement list',EL.Block);
+  L:=AssertListStatement('try..except block is statement list',El.Block);
   AssertAssignStatement('Correct assignment in try..except block',L.A,'a','b');
   AssertNull('No second statement',L.B);
   L:=AssertListStatement('try..except block is statement list',El.BCatch);
   AssertAssignStatement('Correct assignment in except..end block',L.A,'b','c');
-  AssertEquals('Correct exception object name','jsexception',EL.Ident);
+  AssertEquals('Correct exception object name',DefaultJSExceptionObject,El.Ident);
   AssertNull('No second statement',L.B);
 end;
 
@@ -598,17 +603,17 @@ Var
 begin
   // Try a:=B except on E : exception do  b:=c end;
   // Try a:=B except on E : exception do  b:=c end;
-  {
+  (*
     Becomes:
     try {
      a=b;
-    } catch (jsexception) {
-      if jsexception instanceof exception {
-        var e = jsexception;
+    } catch (ExceptObject) {
+      if (ExceptObject instanceof exception) {
+        var e = ExceptObject;
         b = c;
       }
     }
-  }
+  *)
   T:=TPasImplTry.Create('',Nil);
   T.AddElement(CreateAssignStatement('a','b'));
   F:=T.AddExcept;
@@ -616,18 +621,18 @@ begin
   O.Body:=CreateAssignStatement('b','c');
   // Convert
   El:=TJSTryFinallyStatement(Convert(T,TJSTryCatchStatement));
-  AssertEquals('Correct exception object name','jsexception',EL.Ident);
+  AssertEquals('Correct exception object name',DefaultJSExceptionObject,EL.Ident);
   L:=AssertListStatement('try..except block is statement list',El.BCatch);
   AssertNull('No second statement',L.B);
   I:=TJSIfStatement(AssertElement('On block is if',TJSIfStatement,L.A));
   Ic:=TJSRelationalExpressionInstanceOf(AssertElement('If condition is InstanceOf expression',TJSRelationalExpressionInstanceOf,I.Cond));
-  Assertidentifier('InstanceOf left is exception object',Ic.A,'jsexception');
+  Assertidentifier('InstanceOf left is exception object',Ic.A,DefaultJSExceptionObject);
   // Lowercased exception - May need checking
   Assertidentifier('InstanceOf right is original exception type',Ic.B,'exception');
   L:=AssertListStatement('On block is always a list',i.btrue);
   V:=TJSVarDeclaration(AssertElement('First statement in list is a var declaration',TJSVarDeclaration,L.A));
   AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
-  Assertidentifier('Variable init is exception object',v.init,'jsexception');
+  Assertidentifier('Variable init is exception object',v.init,DefaultJSExceptionObject);
   L:=AssertListStatement('Second statement is again list',L.B);
   AssertAssignStatement('Original assignment in second statement',L.A,'b','c');
 end;
@@ -646,7 +651,7 @@ Var
 
 begin
   // Try a:=B except on E : exception do  b:=c end;
-  {
+  (*
     Becomes:
     try {
      a=b;
@@ -656,7 +661,7 @@ begin
         throw jsexception;
       }
     }
-  }
+  *)
   T:=TPasImplTry.Create('',Nil);
   T.AddElement(CreateAssignStatement('a','b'));
   F:=T.AddExcept;
@@ -664,20 +669,20 @@ begin
   O.Body:=TPasImplRaise.Create('',Nil);
   // Convert
   El:=TJSTryFinallyStatement(Convert(T,TJSTryCatchStatement));
-  AssertEquals('Correct exception object name','jsexception',EL.Ident);
+  AssertEquals('Correct exception object name',DefaultJSExceptionObject,EL.Ident);
   L:=AssertListStatement('try..except block is statement list',El.BCatch);
   AssertNull('No second statement',L.B);
   I:=TJSIfStatement(AssertElement('On block is if',TJSIfStatement,L.A));
   Ic:=TJSRelationalExpressionInstanceOf(AssertElement('If condition is InstanceOf expression',TJSRelationalExpressionInstanceOf,I.Cond));
-  Assertidentifier('InstanceOf left is exception object',Ic.A,'jsexception');
+  Assertidentifier('InstanceOf left is exception object',Ic.A,DefaultJSExceptionObject);
   // Lowercased exception - May need checking
   L:=AssertListStatement('On block is always a list',i.btrue);
   V:=TJSVarDeclaration(AssertElement('First statement in list is a var declaration',TJSVarDeclaration,L.A));
   AssertEquals('Variable name is identifier in On A : Ex do','e',V.Name);
-  Assertidentifier('Variable init is exception object',v.init,'jsexception');
+  Assertidentifier('Variable init is exception object',v.init,DefaultJSExceptionObject);
   L:=AssertListStatement('Second statement is again list',L.B);
   R:=TJSThrowStatement(AssertElement('On block is throw statement',TJSThrowStatement,L.A));
-  Assertidentifier('R expression is original exception ',R.A,'jsexception');
+  Assertidentifier('R expression is original exception ',R.A,DefaultJSExceptionObject);
 end;
 
 Procedure TTestStatementConverter.TestVariableStatement;
@@ -1118,8 +1123,6 @@ end;
 Procedure TTestExpressionConverter.TestMemberExpressionArrayTwoDim;
 Var
   B : TParamsExpr;
-  E : TJSBracketMemberExpression;
-
 begin
   // a[b,c];
   B:=TParamsExpr.Create(Nil,pekArrayParams,eopNone);
@@ -1139,7 +1142,7 @@ begin
   R:=TPasVariable.Create('A',Nil);
   VD:=TJSVarDeclaration(Convert(R,TJSVarDeclaration));
   AssertEquals('Correct name, lowercased','a',VD.Name);
-  AssertNull('No init',VD.Init);
+  AssertNotNull('No init',VD.Init);
 end;
 
 Procedure TTestExpressionConverter.TestArrayVariable;
@@ -1156,7 +1159,27 @@ begin
   A:=TJSArrayLiteral(AssertElement('Init is array literal',TJSArrayLiteral,VD.Init));
   AssertEquals('No elements',0,A.Elements.Count);
 end;
-
+procedure TTestExpressionConverter.TestClassDecleration;
+var
+  C: TPasClassType;
+  Decl: TPasDeclarations;
+  Sl: TJSStatementList;
+  Uni: TJSUnary;
+  Asi: TJSSimpleAssignStatement;
+  pex: TJSPrimaryExpressionIdent;
+  Call: TJSCallExpression;
+begin
+  Decl:=TPasDeclarations.Create('',Nil);
+  C:=TPasClassType.Create('myclass',Nil);
+  Decl.Declarations.Add(c);
+  Sl:=TJSStatementList(Convert(Decl,TJSStatementList));
+  Uni:=TJSUnary(AssertElement('Sl.A is TJSUnary',TJSUnary,Sl.A));
+  Asi:=TJSSimpleAssignStatement(AssertElement('Sl.A is TJSUnary',TJSSimpleAssignStatement,Uni.A));
+  pex:=TJSPrimaryExpressionIdent(AssertElement('Asi.LHS is TJSPrimaryExpressionIdent',TJSPrimaryExpressionIdent,Asi.LHS));
+  AssertEquals('Correct name','myclass',pex.Name);
+  Call:=TJSCallExpression(AssertElement('Asi.Expr is TJSCallExpression',TJSCallExpression,Asi.Expr));
+  if Call=nil then ;
+end;
 procedure TTestTestConverter.TestEmpty;
 begin
   AssertNotNull('Have converter',Converter);

+ 0 - 9
packages/pastojs/tests/testpas2js.lpi

@@ -38,17 +38,14 @@
       <Unit0>
         <Filename Value="testpas2js.pp"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="testpas2js"/>
       </Unit0>
       <Unit1>
         <Filename Value="tcconverter.pp"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="tcconverter"/>
       </Unit1>
       <Unit2>
         <Filename Value="../src/fppas2js.pp"/>
         <IsPartOfProject Value="True"/>
-        <UnitName Value="fppas2js"/>
       </Unit2>
     </Units>
   </ProjectOptions>
@@ -58,12 +55,6 @@
       <IncludeFiles Value="$(ProjOutDir)"/>
       <OtherUnitFiles Value="../src"/>
     </SearchPaths>
-    <Other>
-      <CompilerMessages>
-        <MsgFileName Value=""/>
-      </CompilerMessages>
-      <CompilerPath Value="$(CompPath)"/>
-    </Other>
   </CompilerOptions>
   <Debugging>
     <Exceptions Count="3">

Some files were not shown because too many files changed in this diff