diff --git a/packages/fcl-passrc/src/pasresolveeval.pas b/packages/fcl-passrc/src/pasresolveeval.pas index 06d338b25d..6f114ab34c 100644 --- a/packages/fcl-passrc/src/pasresolveeval.pas +++ b/packages/fcl-passrc/src/pasresolveeval.pas @@ -217,6 +217,7 @@ const nAwaitWithoutPromise = 3144; nSymbolCannotBeExportedFromALibrary = 3145; nForLoopControlVarMustBeSimpleLocalVar = 3146; + nIllegalCharConst = 3147; // using same IDs as FPC nVirtualMethodXHasLowerVisibility = 3250; // was 3050 @@ -374,6 +375,7 @@ resourcestring sAwaitWithoutPromise = 'Await without promise'; sSymbolCannotBeExportedFromALibrary = 'The symbol cannot be exported from a library'; sForLoopControlVarMustBeSimpleLocalVar = 'For loop control variable must be simple local variable'; + sIllegalCharConst = 'Illegal char constant'; type { TResolveData - base class for data stored in TPasElement.CustomData } diff --git a/packages/pastojs/src/fppas2js.pp b/packages/pastojs/src/fppas2js.pp index 32db31f955..f206805356 100644 --- a/packages/pastojs/src/fppas2js.pp +++ b/packages/pastojs/src/fppas2js.pp @@ -6750,8 +6750,65 @@ function TPas2JSResolver.ExtractPasStringLiteral(El: TPasElement; Note that invalid UTF-8 sequences are checked by the scanner } var - p, StartP, i, l: integer; + p, StartP, l: integer; + + procedure Err(id: TMaxPrecInt); + begin + RaiseMsg(id,nIllegalCharConst,sIllegalCharConst,[],El); + end; + + function ReadNumber: integer; + var + c: AnsiChar; + begin + Result:=0; + inc(p); + if p>l then + Err(20170207155121); + if S[p]='$' then + begin + // #$hexnumber + inc(p); + StartP:=p; + while p<=l do + begin + c:=S[p]; + case c of + '0'..'9': Result:=Result*16+ord(c)-ord('0'); + 'a'..'f': Result:=Result*16+ord(c)-ord('a')+10; + 'A'..'F': Result:=Result*16+ord(c)-ord('A')+10; + else break; + end; + if Result>$10ffff then + RaiseNotYetImplemented(20170207164657,El,'maximum codepoint is $10ffff'); + inc(p); + end; + if p=StartP then + Err(20170207164956); + end + else + begin + // #decimalnumber + StartP:=p; + while p<=l do + begin + c:=S[p]; + case c of + '0'..'9': Result:=Result*10+ord(c)-ord('0'); + else break; + end; + if Result>$10ffff then + Err(20170207171140); + inc(p); + end; + if p=StartP then + Err(20170207171148); + end; + end; + +var c: AnsiChar; + i, j: Integer; begin Result:=''; {$IFDEF VerbosePas2JS} @@ -6769,7 +6826,7 @@ begin StartP:=p; repeat if p>l then - RaiseInternalError(20170207155120); + Err(20170207155120); c:=S[p]; case c of '''': @@ -6793,69 +6850,36 @@ begin end; '#': begin - // word sequence - inc(p); - if p>l then - RaiseInternalError(20170207155121); - if S[p]='$' then + // number + i:=ReadNumber; + if (i>=$D800) and (i<=$DFFF) and (p$10ffff then - RaiseNotYetImplemented(20170207164657,El,'maximum codepoint is $10ffff'); - inc(p); - end; - if p=StartP then - RaiseInternalError(20170207164956); + // surrogate + j:=ReadNumber; + if (j>=$DC00) and (j<$DFFF) then + Result:=Result+CodePointToJSString((i and $3FF) shl 10 + (j and $3ff) + $10000) + else + Err(20231017120034); end else - begin - // #decimalnumber - StartP:=p; - i:=0; - while p<=l do - begin - c:=S[p]; - case c of - '0'..'9': i:=i*10+ord(c)-ord('0'); - else break; - end; - if i>$10ffff then - RaiseNotYetImplemented(20170207171140,El,'maximum codepoint is $10ffff'); - inc(p); - end; - if p=StartP then - RaiseInternalError(20170207171148); - end; - Result:=Result+CodePointToJSString(i); + Result:=Result+CodePointToJSString(i); end; '^': begin // ^A is #1 inc(p); if p>l then - RaiseInternalError(20181025125920); + Err(20181025125920); c:=S[p]; case c of 'a'..'z': Result:=Result+TJSChar(ord(c)-ord('a')+1); 'A'..'Z': Result:=Result+TJSChar(ord(c)-ord('A')+1); - else RaiseInternalError(20170207160412); + else Err(20170207160412); end; inc(p); end; else - RaiseNotYetImplemented(20170207154653,El,'ord='+IntToStr(ord(S[p]))); + Err(20170207154653); end; {$IFDEF VerbosePas2JS} {AllowWriteln}