Browse Source

fcl-js: adapted jswriter for pas2js

git-svn-id: trunk@39898 -
Mattias Gaertner 6 years ago
parent
commit
ddf409d7ad
2 changed files with 58 additions and 52 deletions
  1. 3 0
      packages/fcl-js/src/jsbase.pp
  2. 55 52
      packages/fcl-js/src/jswriter.pp

+ 3 - 0
packages/fcl-js/src/jsbase.pp

@@ -25,6 +25,9 @@ uses
   {$endif}
   Classes, SysUtils;
 
+const
+  MinSafeIntDouble = -$10000000000000; // -4503599627370496
+  MaxSafeIntDouble =   $fffffffffffff; //  4503599627370495
 Type
   TJSType = (jstUNDEFINED,jstNull,jstBoolean,jstNumber,jstString,jstObject,jstReference,jstCompletion);
 

+ 55 - 52
packages/fcl-js/src/jswriter.pp

@@ -517,26 +517,26 @@ function TJSWriter.EscapeString(const S: TJSString; Quote: TJSEscapeQuote
 
 Var
   I,J,L : Integer;
-  P : TJSPChar;
   R: TJSString;
+  c: Char;
 
 begin
   I:=1;
   J:=1;
   R:='';
   L:=Length(S);
-  P:=TJSPChar(S);
   While I<=L do
     begin
-    if (P^ in [#0..#31,'"','''','/','\']) then
+    c:=S[I];
+    if (c in [#0..#31,'"','''','/','\']) then
       begin
       R:=R+Copy(S,J,I-J);
-      Case P^ of
+      Case c of
         '\' : R:=R+'\\';
         '/' : R:=R+'\/';
         '"' : if Quote=jseqSingle then R:=R+'"' else R:=R+'\"';
         '''': if Quote=jseqDouble then R:=R+'''' else R:=R+'\''';
-        #0..#7,#11,#14..#31: R:=R+'\x'+TJSString(hexStr(ord(P^),2));
+        #0..#7,#11,#14..#31: R:=R+'\x'+TJSString(hexStr(ord(c),2));
         #8  : R:=R+'\b';
         #9  : R:=R+'\t';
         #10 : R:=R+'\n';
@@ -546,7 +546,6 @@ begin
       J:=I+1;
       end;
     Inc(I);
-    Inc(P);
     end;
   R:=R+Copy(S,J,I-1);
   Result:=R;
@@ -556,32 +555,36 @@ procedure TJSWriter.WriteValue(V: TJSValue);
 const
   TabWidth = 4;
 
-  function GetLineIndent(var p: PWideChar): integer;
+  function GetLineIndent(const S: TJSString; var p: integer): integer;
   var
-    h: PWideChar;
+    h, l: integer;
   begin
     h:=p;
+    l:=length(S);
     Result:=0;
-    repeat
-      case h^ of
-      #0: break;
+    while h<=l do
+      begin
+      case S[h] of
       #9: Result:=Result+(TabWidth-Result mod TabWidth);
       ' ': inc(Result);
       else break;
       end;
       inc(h);
-    until false;
+      end;
     p:=h;
   end;
 
-  function SkipToNextLineStart(p: PWideChar): PWideChar;
+  function SkipToNextLineStart(const S: TJSString; p: integer): integer;
+  var
+    l: Integer;
   begin
-    repeat
-      case p^ of
-      #0: break;
+    l:=length(S);
+    while p<=l do
+      begin
+      case S[p] of
       #10,#13:
         begin
-        if (p[1] in [#10,#13]) and (p^<>p[1]) then
+        if (p<l) and (S[p+1] in [#10,#13]) and (S[p]<>S[p+1]) then
           inc(p,2)
         else
           inc(p);
@@ -589,14 +592,14 @@ const
         end
       else inc(p);
       end;
-    until false;
+      end;
     Result:=p;
   end;
 
 Var
   S , S2: String;
   JS: TJSString;
-  p, StartP: PWideChar;
+  p, StartP: Integer;
   MinIndent, CurLineIndent, j, Exp, Code: Integer;
   i: SizeInt;
   D: TJSNumber;
@@ -606,8 +609,8 @@ begin
     JS:=V.CustomValue;
     if JS='' then exit;
 
-    p:=SkipToNextLineStart(PWideChar(JS));
-    if p^=#0 then
+    p:=SkipToNextLineStart(JS,1);
+    if p>length(JS) then
       begin
       // simple value
       Write(JS);
@@ -619,21 +622,21 @@ begin
     // find minimum indent
     MinIndent:=-1;
     repeat
-      CurLineIndent:=GetLineIndent(p);
+      CurLineIndent:=GetLineIndent(JS,p);
       if (MinIndent<0) or (MinIndent>CurLineIndent) then
         MinIndent:=CurLineIndent;
-      p:=SkipToNextLineStart(p);
-    until p^=#0;
+      p:=SkipToNextLineStart(JS,p);
+    until p>length(JS);
 
     // write value lines indented
-    p:=PWideChar(JS);
-    GetLineIndent(p); // the first line is already indented, skip
+    p:=1;
+    GetLineIndent(JS,p); // the first line is already indented, skip
     repeat
       StartP:=p;
-      p:=SkipToNextLineStart(StartP);
-      Write(copy(JS,StartP-PWideChar(JS)+1,p-StartP));
-      if p^=#0 then break;
-      CurLineIndent:=GetLineIndent(p);
+      p:=SkipToNextLineStart(JS,StartP);
+      Write(copy(JS,StartP,p-StartP));
+      if p>length(JS) then break;
+      CurLineIndent:=GetLineIndent(JS,p);
       Write(StringOfChar(FIndentChar,FCurIndent+CurLineIndent-MinIndent));
     until false;
 
@@ -655,8 +658,8 @@ begin
       end;
     jstNumber :
       if (Frac(V.AsNumber)=0)
-          and (V.AsNumber>double(low(int64)))
-          and (V.AsNumber<double(high(int64))) then
+          and (V.AsNumber>=double(MinSafeIntDouble))
+          and (V.AsNumber<=double(MaxSafeIntDouble)) then
         begin
         Str(Round(V.AsNumber),S);
         end
@@ -796,7 +799,7 @@ constructor TJSWriter.Create(AWriter: TTextWriter);
 begin
   FWriter:=AWriter;
   FIndentChar:=' ';
-  FOptions:=[woUseUTF8];
+  FOptions:=[{$ifdef fpc}woUseUTF8{$endif}];
 end;
 
 {$ifdef fpc}
@@ -918,13 +921,15 @@ end;
 
 procedure TJSWriter.WriteArrayLiteral(El: TJSArrayLiteral);
 
+type
+  BracketString = string{$ifdef fpc}[2]{$endif};
 Var
-  Chars : Array[Boolean] of string[2] = ('[]','()');
+  Chars : Array[Boolean] of BracketString = ('[]','()');
 
 Var
   i,C : Integer;
   isArgs,WC , MultiLine: Boolean;
-  BC : String[2];
+  BC : BracketString;
 
 begin
   isArgs:=El is TJSArguments;
@@ -1201,7 +1206,7 @@ end;
 procedure TJSWriter.WriteBinary(El: TJSBinary);
 
 Var
-  S : AnsiString;
+  S : String;
   AllowCompact, WithBrackets: Boolean;
 begin
   {$IFDEF VerboseJSWriter}
@@ -1278,7 +1283,7 @@ end;
 procedure TJSWriter.WriteAssignStatement(El: TJSAssignStatement);
 
 Var
-  S : AnsiString;
+  S : String;
 begin
   WriteJS(El.LHS);
   Writer.CurElement:=El;
@@ -1827,6 +1832,7 @@ begin
   FCurColumn:=1;
 end;
 
+{$ifdef fpc}
 function TTextWriter.Write(const S: UnicodeString): Integer;
 var
   p: PWideChar;
@@ -1859,38 +1865,35 @@ begin
     inc(p);
   until false;
 end;
+{$endif}
 
 function TTextWriter.Write(const S: TJSWriterString): Integer;
 var
-  p: PChar;
   c: Char;
+  l, p: Integer;
 begin
   if S='' then exit;
   Writing;
   Result:=DoWrite(S);
-  p:=PChar(S);
-  repeat
-    c:=p^;
+  l:=length(S);
+  p:=1;
+  while p<=l do
+    begin
+    c:=S[p];
     case c of
-    #0:
-      if p-PChar(S)=length(S) then
-        break
-      else
-        inc(FCurColumn);
     #10,#13:
       begin
       FCurColumn:=1;
       inc(FCurLine);
       inc(p);
-      if (p^ in [#10,#13]) and (c<>p^) then inc(p);
-      continue;
+      if (p<=l) and (S[p] in [#10,#13]) and (c<>S[p]) then inc(p);
       end;
     else
-      // ignore UTF-8 multibyte chars, CurColumn is char index, not codepoint
+      // Note about UTF-8 multibyte chars: CurColumn is char index, not codepoint
       inc(FCurColumn);
+      inc(p);
+    end;
     end;
-    inc(p);
-  until false;
 end;
 
 function TTextWriter.WriteLn(const S: TJSWriterString): Integer;
@@ -1933,7 +1936,7 @@ begin
     {$ifdef pas2js}
     case jsTypeOf(V) of
     'boolean':
-      S:=if V then S:='true' else S:='false';
+      if V then S:='true' else S:='false';
     'number':
       if isInteger(V) then
         S:=str(NativeInt(V))