mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-08 08:48:02 +01:00
* Patch from Mattias Gaertner
- quote object keys if needed { "1":"value" }
- use " or ' for string literals
git-svn-id: trunk@35416 -
This commit is contained in:
parent
203bd85c38
commit
55241e283f
@ -26,6 +26,8 @@ Type
|
|||||||
TJSType = (jstUNDEFINED,jstNull,jstBoolean,jstNumber,jstString,jstObject,jstReference,JSTCompletion);
|
TJSType = (jstUNDEFINED,jstNull,jstBoolean,jstNumber,jstString,jstObject,jstReference,JSTCompletion);
|
||||||
|
|
||||||
TJSString = UnicodeString;
|
TJSString = UnicodeString;
|
||||||
|
TJSChar = WideChar;
|
||||||
|
TJSPChar = PWideChar;
|
||||||
TJSNumber = Double;
|
TJSNumber = Double;
|
||||||
|
|
||||||
{ TJSValue }
|
{ TJSValue }
|
||||||
|
|||||||
@ -83,8 +83,14 @@ Type
|
|||||||
Property AsUnicodeString : UnicodeString Read GetUnicodeString;
|
Property AsUnicodeString : UnicodeString Read GetUnicodeString;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
TJSEscapeQuote = (
|
||||||
|
jseqSingle,
|
||||||
|
jseqDouble,
|
||||||
|
jseqBoth
|
||||||
|
);
|
||||||
|
|
||||||
{ TJSWriter }
|
{ TJSWriter }
|
||||||
|
|
||||||
TWriteOption = (woCompact,
|
TWriteOption = (woCompact,
|
||||||
woUseUTF8,
|
woUseUTF8,
|
||||||
woTabIndent,
|
woTabIndent,
|
||||||
@ -151,7 +157,7 @@ Type
|
|||||||
Procedure WritePrimaryExpression(El: TJSPrimaryExpression);virtual;
|
Procedure WritePrimaryExpression(El: TJSPrimaryExpression);virtual;
|
||||||
Procedure WriteBinary(El: TJSBinary);virtual;
|
Procedure WriteBinary(El: TJSBinary);virtual;
|
||||||
Public
|
Public
|
||||||
Function EscapeString(const S: TJSString): String;
|
Function EscapeString(const S: TJSString; Quote: TJSEscapeQuote = jseqDouble): String;
|
||||||
Function JSStringToStr(const S: TJSString): string;
|
Function JSStringToStr(const S: TJSString): string;
|
||||||
Constructor Create(AWriter : TTextWriter);
|
Constructor Create(AWriter : TTextWriter);
|
||||||
Constructor Create(Const AFileName : String);
|
Constructor Create(Const AFileName : String);
|
||||||
@ -164,7 +170,9 @@ Type
|
|||||||
Property IndentSize : Byte Read FIndentSize Write FIndentSize;
|
Property IndentSize : Byte Read FIndentSize Write FIndentSize;
|
||||||
Property UseUTF8 : Boolean Read GetUseUTF8;
|
Property UseUTF8 : Boolean Read GetUseUTF8;
|
||||||
end;
|
end;
|
||||||
EJSWriter = CLass(Exception);
|
EJSWriter = Class(Exception);
|
||||||
|
|
||||||
|
function IsValidJSIdentifier(Name: TJSString; AllowEscapeSeq: boolean = false): boolean;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
@ -172,6 +180,85 @@ Resourcestring
|
|||||||
SErrUnknownJSClass = 'Unknown javascript element class : %s';
|
SErrUnknownJSClass = 'Unknown javascript element class : %s';
|
||||||
SErrNilNode = 'Nil node in Javascript';
|
SErrNilNode = 'Nil node in Javascript';
|
||||||
|
|
||||||
|
function IsValidJSIdentifier(Name: TJSString; AllowEscapeSeq: boolean): boolean;
|
||||||
|
var
|
||||||
|
p: TJSPChar;
|
||||||
|
i: Integer;
|
||||||
|
begin
|
||||||
|
Result:=false;
|
||||||
|
if Name='' then exit;
|
||||||
|
p:=TJSPChar(Name);
|
||||||
|
repeat
|
||||||
|
case p^ of
|
||||||
|
#0:
|
||||||
|
if p-TJSPChar(Name)=length(Name) then
|
||||||
|
exit(true)
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
'0'..'9':
|
||||||
|
if p=TJSPChar(Name) then
|
||||||
|
exit
|
||||||
|
else
|
||||||
|
inc(p);
|
||||||
|
'a'..'z','A'..'Z','_','$': inc(p);
|
||||||
|
'\':
|
||||||
|
begin
|
||||||
|
if not AllowEscapeSeq then exit;
|
||||||
|
inc(p);
|
||||||
|
if p^='x' then
|
||||||
|
begin
|
||||||
|
// \x00
|
||||||
|
for i:=1 to 2 do
|
||||||
|
begin
|
||||||
|
inc(p);
|
||||||
|
if not (p^ in ['0'..'9','a'..'f','A'..'F']) then exit;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else if p^='u' then
|
||||||
|
begin
|
||||||
|
inc(p);
|
||||||
|
if p^='{' then
|
||||||
|
begin
|
||||||
|
// \u{00000}
|
||||||
|
i:=0;
|
||||||
|
repeat
|
||||||
|
inc(p);
|
||||||
|
case p^ of
|
||||||
|
'}': break;
|
||||||
|
'0'..'9': i:=i*16+ord(p^)-ord('0');
|
||||||
|
'a'..'f': i:=i*16+ord(p^)-ord('a')+10;
|
||||||
|
'A'..'F': i:=i*16+ord(p^)-ord('A')+10;
|
||||||
|
else exit;
|
||||||
|
end;
|
||||||
|
if i>$10FFFF then exit;
|
||||||
|
until false;
|
||||||
|
inc(p);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
// \u0000
|
||||||
|
for i:=1 to 4 do
|
||||||
|
begin
|
||||||
|
inc(p);
|
||||||
|
if not (p^ in ['0'..'9','a'..'f','A'..'F']) then exit;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
exit; // unknown sequence
|
||||||
|
end;
|
||||||
|
#$200C,#$200D: inc(p); // zero width non-joiner/joiner
|
||||||
|
#$00AA..#$2000,
|
||||||
|
#$200E..#$D7FF:
|
||||||
|
inc(p); // ToDo: only those with ID_START/ID_CONTINUE see https://codepoints.net/search?IDC=1
|
||||||
|
#$D800..#$DBFF:
|
||||||
|
inc(p,2); // see above
|
||||||
|
else
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
until false;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TBufferWriter }
|
{ TBufferWriter }
|
||||||
|
|
||||||
function TBufferWriter.GetBufferLength: Integer;
|
function TBufferWriter.GetBufferLength: Integer;
|
||||||
@ -380,27 +467,30 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TJSWriter.EscapeString(const S: TJSString): String;
|
function TJSWriter.EscapeString(const S: TJSString; Quote: TJSEscapeQuote
|
||||||
|
): String;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
I,J,L : Integer;
|
I,J,L : Integer;
|
||||||
P : PWideChar;
|
P : TJSPChar;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
I:=1;
|
I:=1;
|
||||||
J:=1;
|
J:=1;
|
||||||
Result:='';
|
Result:='';
|
||||||
L:=Length(S);
|
L:=Length(S);
|
||||||
P:=PWideChar(S);
|
P:=TJSPChar(S);
|
||||||
While I<=L do
|
While I<=L do
|
||||||
begin
|
begin
|
||||||
if (P^ in ['"','/','\',#8,#9,#10,#12,#13]) then
|
if (P^ in [#0..#31,'"','''','/','\']) then
|
||||||
begin
|
begin
|
||||||
Result:=Result+JSStringToStr(Copy(S,J,I-J));
|
Result:=Result+JSStringToStr(Copy(S,J,I-J));
|
||||||
Case P^ of
|
Case P^ of
|
||||||
'\' : Result:=Result+'\\';
|
'\' : Result:=Result+'\\';
|
||||||
'/' : Result:=Result+'\/';
|
'/' : Result:=Result+'\/';
|
||||||
'"' : Result:=Result+'\"';
|
'"' : if Quote=jseqSingle then Result:=Result+'"' else Result:=Result+'\"';
|
||||||
|
'''': if Quote=jseqDouble then Result:=Result+'''' else Result:=Result+'\''';
|
||||||
|
#0..#7,#11,#14..#31: Result:=Result+'\x'+hexStr(ord(P^),2);
|
||||||
#8 : Result:=Result+'\b';
|
#8 : Result:=Result+'\b';
|
||||||
#9 : Result:=Result+'\t';
|
#9 : Result:=Result+'\t';
|
||||||
#10 : Result:=Result+'\n';
|
#10 : Result:=Result+'\n';
|
||||||
@ -427,6 +517,7 @@ procedure TJSWriter.WriteValue(V: TJSValue);
|
|||||||
|
|
||||||
Var
|
Var
|
||||||
S : String;
|
S : String;
|
||||||
|
JS: TJSString;
|
||||||
begin
|
begin
|
||||||
if V.CustomValue<>'' then
|
if V.CustomValue<>'' then
|
||||||
S:=JSStringToStr(V.CustomValue)
|
S:=JSStringToStr(V.CustomValue)
|
||||||
@ -435,7 +526,14 @@ begin
|
|||||||
jstUNDEFINED : S:='undefined';
|
jstUNDEFINED : S:='undefined';
|
||||||
jstNull : s:='null';
|
jstNull : s:='null';
|
||||||
jstBoolean : if V.AsBoolean then s:='true' else s:='false';
|
jstBoolean : if V.AsBoolean then s:='true' else s:='false';
|
||||||
jstString : S:='"'+EscapeString(V.AsString)+'"';
|
jstString :
|
||||||
|
begin
|
||||||
|
JS:=V.AsString;
|
||||||
|
if Pos('"',JS)>0 then
|
||||||
|
S:=''''+EscapeString(JS,jseqSingle)+''''
|
||||||
|
else
|
||||||
|
S:='"'+EscapeString(JS,jseqDouble)+'"';
|
||||||
|
end;
|
||||||
jstNumber :
|
jstNumber :
|
||||||
if Frac(V.AsNumber)=0 then // this needs to be improved
|
if Frac(V.AsNumber)=0 then // this needs to be improved
|
||||||
Str(Round(V.AsNumber),S)
|
Str(Round(V.AsNumber),S)
|
||||||
@ -544,10 +642,10 @@ procedure TJSWriter.WriteRegularExpressionLiteral(
|
|||||||
|
|
||||||
begin
|
begin
|
||||||
Write('/');
|
Write('/');
|
||||||
Write(EscapeString(El.Pattern.AsString));
|
Write(EscapeString(El.Pattern.AsString,jseqBoth));
|
||||||
Write('/');
|
Write('/');
|
||||||
If Assigned(El.PatternFlags) then
|
If Assigned(El.PatternFlags) then
|
||||||
Write(EscapeString(El.PatternFlags.AsString));
|
Write(EscapeString(El.PatternFlags.AsString,jseqBoth));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TJSWriter.WriteLiteral(El: TJSLiteral);
|
procedure TJSWriter.WriteLiteral(El: TJSLiteral);
|
||||||
@ -642,7 +740,7 @@ begin
|
|||||||
For I:=0 to C do
|
For I:=0 to C do
|
||||||
begin
|
begin
|
||||||
S:=El.Elements[i].Name;
|
S:=El.Elements[i].Name;
|
||||||
if QE then
|
if QE or not IsValidJSIdentifier(S) then
|
||||||
S:='"'+S+'"';
|
S:='"'+S+'"';
|
||||||
Write(S+': ');
|
Write(S+': ');
|
||||||
Indent;
|
Indent;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user