mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-04 13:47:23 +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);
|
||||
|
||||
TJSString = UnicodeString;
|
||||
TJSChar = WideChar;
|
||||
TJSPChar = PWideChar;
|
||||
TJSNumber = Double;
|
||||
|
||||
{ TJSValue }
|
||||
|
||||
@ -83,8 +83,14 @@ Type
|
||||
Property AsUnicodeString : UnicodeString Read GetUnicodeString;
|
||||
end;
|
||||
|
||||
TJSEscapeQuote = (
|
||||
jseqSingle,
|
||||
jseqDouble,
|
||||
jseqBoth
|
||||
);
|
||||
|
||||
{ TJSWriter }
|
||||
|
||||
TWriteOption = (woCompact,
|
||||
woUseUTF8,
|
||||
woTabIndent,
|
||||
@ -151,7 +157,7 @@ Type
|
||||
Procedure WritePrimaryExpression(El: TJSPrimaryExpression);virtual;
|
||||
Procedure WriteBinary(El: TJSBinary);virtual;
|
||||
Public
|
||||
Function EscapeString(const S: TJSString): String;
|
||||
Function EscapeString(const S: TJSString; Quote: TJSEscapeQuote = jseqDouble): String;
|
||||
Function JSStringToStr(const S: TJSString): string;
|
||||
Constructor Create(AWriter : TTextWriter);
|
||||
Constructor Create(Const AFileName : String);
|
||||
@ -164,7 +170,9 @@ Type
|
||||
Property IndentSize : Byte Read FIndentSize Write FIndentSize;
|
||||
Property UseUTF8 : Boolean Read GetUseUTF8;
|
||||
end;
|
||||
EJSWriter = CLass(Exception);
|
||||
EJSWriter = Class(Exception);
|
||||
|
||||
function IsValidJSIdentifier(Name: TJSString; AllowEscapeSeq: boolean = false): boolean;
|
||||
|
||||
implementation
|
||||
|
||||
@ -172,6 +180,85 @@ Resourcestring
|
||||
SErrUnknownJSClass = 'Unknown javascript element class : %s';
|
||||
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 }
|
||||
|
||||
function TBufferWriter.GetBufferLength: Integer;
|
||||
@ -380,27 +467,30 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TJSWriter.EscapeString(const S: TJSString): String;
|
||||
function TJSWriter.EscapeString(const S: TJSString; Quote: TJSEscapeQuote
|
||||
): String;
|
||||
|
||||
Var
|
||||
I,J,L : Integer;
|
||||
P : PWideChar;
|
||||
P : TJSPChar;
|
||||
|
||||
begin
|
||||
I:=1;
|
||||
J:=1;
|
||||
Result:='';
|
||||
L:=Length(S);
|
||||
P:=PWideChar(S);
|
||||
P:=TJSPChar(S);
|
||||
While I<=L do
|
||||
begin
|
||||
if (P^ in ['"','/','\',#8,#9,#10,#12,#13]) then
|
||||
if (P^ in [#0..#31,'"','''','/','\']) then
|
||||
begin
|
||||
Result:=Result+JSStringToStr(Copy(S,J,I-J));
|
||||
Case P^ of
|
||||
'\' : 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';
|
||||
#9 : Result:=Result+'\t';
|
||||
#10 : Result:=Result+'\n';
|
||||
@ -427,6 +517,7 @@ procedure TJSWriter.WriteValue(V: TJSValue);
|
||||
|
||||
Var
|
||||
S : String;
|
||||
JS: TJSString;
|
||||
begin
|
||||
if V.CustomValue<>'' then
|
||||
S:=JSStringToStr(V.CustomValue)
|
||||
@ -435,7 +526,14 @@ begin
|
||||
jstUNDEFINED : S:='undefined';
|
||||
jstNull : s:='null';
|
||||
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 :
|
||||
if Frac(V.AsNumber)=0 then // this needs to be improved
|
||||
Str(Round(V.AsNumber),S)
|
||||
@ -544,10 +642,10 @@ procedure TJSWriter.WriteRegularExpressionLiteral(
|
||||
|
||||
begin
|
||||
Write('/');
|
||||
Write(EscapeString(El.Pattern.AsString));
|
||||
Write(EscapeString(El.Pattern.AsString,jseqBoth));
|
||||
Write('/');
|
||||
If Assigned(El.PatternFlags) then
|
||||
Write(EscapeString(El.PatternFlags.AsString));
|
||||
Write(EscapeString(El.PatternFlags.AsString,jseqBoth));
|
||||
end;
|
||||
|
||||
procedure TJSWriter.WriteLiteral(El: TJSLiteral);
|
||||
@ -642,7 +740,7 @@ begin
|
||||
For I:=0 to C do
|
||||
begin
|
||||
S:=El.Elements[i].Name;
|
||||
if QE then
|
||||
if QE or not IsValidJSIdentifier(S) then
|
||||
S:='"'+S+'"';
|
||||
Write(S+': ');
|
||||
Indent;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user