JSON.parse errors made user-friendly
Part of the improve error messages initiative. Based on a resource of JSON.parse() errors found at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/JSON_bad_parse Previously JSON.parse(NaN) would output: SyntaxError: Unexpected token N in JSON at position 0 Now the output is: SyntaxError: "NaN" is not valid JSON Previously JSON.parse("{a:1}") would output: SyntaxError: Unexpected token a in JSON at position 1 Now the output is: SyntaxError: Expected property name or '}' in JSON at position 1 Bug: v8:6551 Change-Id: Ic9fad1fdbd295e1302805b81e6603fc526121960 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3513684 Reviewed-by: Toon Verwaest <verwaest@chromium.org> Commit-Queue: Issack John <issackjohn@microsoft.com> Cr-Commit-Position: refs/heads/main@{#80567}
This commit is contained in:
parent
b9420be7a2
commit
718f743750
@ -481,9 +481,40 @@ namespace internal {
|
||||
T(InvalidUnusedPrivateStaticMethodAccessedByDebugger, \
|
||||
"Unused static private method '%' cannot be accessed at debug time") \
|
||||
T(JsonParseUnexpectedEOS, "Unexpected end of JSON input") \
|
||||
T(JsonParseUnexpectedToken, "Unexpected token % in JSON at position %") \
|
||||
T(JsonParseUnexpectedTokenNumber, "Unexpected number in JSON at position %") \
|
||||
T(JsonParseUnexpectedTokenString, "Unexpected string in JSON at position %") \
|
||||
T(JsonParseUnterminatedString, "Unterminated string in JSON at position %") \
|
||||
T(JsonParseExpectedPropNameOrRBrace, \
|
||||
"Expected property name or '}' in JSON at position %") \
|
||||
T(JsonParseExpectedCommaOrRBrack, \
|
||||
"Expected ',' or ']' after array element in JSON at position %") \
|
||||
T(JsonParseExpectedCommaOrRBrace, \
|
||||
"Expected ',' or '}' after property value in JSON at position " \
|
||||
"%") \
|
||||
T(JsonParseExpectedDoubleQuotedPropertyName, \
|
||||
"Expected double-quoted property name in JSON at position %") \
|
||||
T(JsonParseExponentPartMissingNumber, \
|
||||
"Exponent part is missing a number in JSON at position %") \
|
||||
T(JsonParseExpectedColonAfterPropertyName, \
|
||||
"Expected ':' after property name in JSON at position %") \
|
||||
T(JsonParseUnterminatedFractionalNumber, \
|
||||
"Unterminated fractional number in JSON at position %") \
|
||||
T(JsonParseUnexpectedNonWhiteSpaceCharacter, \
|
||||
"Unexpected non-whitespace character after JSON at position " \
|
||||
"%") \
|
||||
T(JsonParseBadEscapedCharacter, \
|
||||
"Bad escaped character in JSON at position %") \
|
||||
T(JsonParseNoNumberAfterMinusSign, \
|
||||
"No number after minus sign in JSON at position %") \
|
||||
T(JsonParseShortString, "\"%\" is not valid JSON") \
|
||||
T(JsonParseUnexpectedTokenShortString, \
|
||||
"Unexpected token '%', \"%\" is not valid JSON") \
|
||||
T(JsonParseUnexpectedTokenSurroundStringWithContext, \
|
||||
"Unexpected token '%', ...\"%\"... is not valid JSON") \
|
||||
T(JsonParseUnexpectedTokenEndStringWithContext, \
|
||||
"Unexpected token '%', ...\"%\" is not valid JSON") \
|
||||
T(JsonParseUnexpectedTokenStartStringWithContext, \
|
||||
"Unexpected token '%', \"%\"... is not valid JSON") \
|
||||
T(LabelRedeclaration, "Label '%' has already been declared") \
|
||||
T(LabelledFunctionDeclaration, \
|
||||
"Labelled function declaration not allowed as the body of a control flow " \
|
||||
|
@ -240,20 +240,75 @@ JsonParser<Char>::JsonParser(Isolate* isolate, Handle<String> source)
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void JsonParser<Char>::ReportUnexpectedToken(JsonToken token) {
|
||||
// Some exception (for example stack overflow) is already pending.
|
||||
if (isolate_->has_pending_exception()) return;
|
||||
|
||||
// Parse failed. Current character is the unexpected token.
|
||||
Factory* factory = this->factory();
|
||||
MessageTemplate message;
|
||||
bool JsonParser<Char>::IsSpecialString() {
|
||||
// The special cases are undefined, NaN, Infinity, and {} being passed to the
|
||||
// parse method
|
||||
int offset = original_source_->IsSlicedString()
|
||||
? SlicedString::cast(*original_source_).offset()
|
||||
: 0;
|
||||
int pos = position() - offset;
|
||||
Handle<Object> arg1 = Handle<Smi>(Smi::FromInt(pos), isolate());
|
||||
Handle<Object> arg2;
|
||||
size_t length = original_source_->length();
|
||||
#define CASES(V) \
|
||||
V("[object Object]") \
|
||||
V("undefined") \
|
||||
V("Infinity") \
|
||||
V("NaN")
|
||||
switch (length) {
|
||||
#define CASE(n) \
|
||||
case arraysize(n) - 1: \
|
||||
return CompareCharsEqual(chars_ + offset, n, arraysize(n) - 1);
|
||||
CASES(CASE)
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
#undef CASE
|
||||
#undef CASES
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
MessageTemplate JsonParser<Char>::GetErrorMessageWithEllipses(
|
||||
Handle<Object>& arg, Handle<Object>& arg2, int pos) {
|
||||
MessageTemplate message;
|
||||
Factory* factory = this->factory();
|
||||
arg = factory->LookupSingleCharacterStringFromCode(*cursor_);
|
||||
int origin_source_length = original_source_->length();
|
||||
// only provide context for strings with at least
|
||||
// kMinOriginalSourceLengthForContext charcacters in length
|
||||
if (origin_source_length >= kMinOriginalSourceLengthForContext) {
|
||||
int substring_start = 0;
|
||||
int substring_end = origin_source_length;
|
||||
if (pos < kMaxContextCharacters) {
|
||||
message =
|
||||
MessageTemplate::kJsonParseUnexpectedTokenStartStringWithContext;
|
||||
// Output the string followed by elipses
|
||||
substring_end = pos + kMaxContextCharacters;
|
||||
} else if (pos >= kMaxContextCharacters &&
|
||||
pos < origin_source_length - kMaxContextCharacters) {
|
||||
message =
|
||||
MessageTemplate::kJsonParseUnexpectedTokenSurroundStringWithContext;
|
||||
// Add context before and after position of bad token surrounded by
|
||||
// elipses
|
||||
substring_start = pos - kMaxContextCharacters;
|
||||
substring_end = pos + kMaxContextCharacters;
|
||||
} else {
|
||||
message = MessageTemplate::kJsonParseUnexpectedTokenEndStringWithContext;
|
||||
// Add ellipses followed by some context before bad token
|
||||
substring_start = pos - kMaxContextCharacters;
|
||||
}
|
||||
arg2 =
|
||||
factory->NewSubString(original_source_, substring_start, substring_end);
|
||||
} else {
|
||||
arg2 = original_source_;
|
||||
// Output the entire string without ellipses but provide the token which
|
||||
// was unexpected
|
||||
message = MessageTemplate::kJsonParseUnexpectedTokenShortString;
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
MessageTemplate JsonParser<Char>::LookUpErrorMessageForJsonToken(
|
||||
JsonToken token, Handle<Object>& arg, Handle<Object>& arg2, int pos) {
|
||||
MessageTemplate message;
|
||||
switch (token) {
|
||||
case JsonToken::EOS:
|
||||
message = MessageTemplate::kJsonParseUnexpectedEOS;
|
||||
@ -265,11 +320,36 @@ void JsonParser<Char>::ReportUnexpectedToken(JsonToken token) {
|
||||
message = MessageTemplate::kJsonParseUnexpectedTokenString;
|
||||
break;
|
||||
default:
|
||||
message = MessageTemplate::kJsonParseUnexpectedToken;
|
||||
arg2 = arg1;
|
||||
arg1 = factory->LookupSingleCharacterStringFromCode(*cursor_);
|
||||
break;
|
||||
// Output entire string without ellipses and don't provide the token
|
||||
// that was unexpected because it makes the error messages more confusing
|
||||
if (IsSpecialString()) {
|
||||
arg = original_source_;
|
||||
message = MessageTemplate::kJsonParseShortString;
|
||||
} else {
|
||||
message = GetErrorMessageWithEllipses(arg, arg2, pos);
|
||||
}
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
template <typename Char>
|
||||
void JsonParser<Char>::ReportUnexpectedToken(
|
||||
JsonToken token, base::Optional<MessageTemplate> errorMessage) {
|
||||
// Some exception (for example stack overflow) is already pending.
|
||||
if (isolate_->has_pending_exception()) return;
|
||||
|
||||
// Parse failed. Current character is the unexpected token.
|
||||
Factory* factory = this->factory();
|
||||
int offset = original_source_->IsSlicedString()
|
||||
? SlicedString::cast(*original_source_).offset()
|
||||
: 0;
|
||||
int pos = position() - offset;
|
||||
Handle<Object> arg(Smi::FromInt(pos), isolate());
|
||||
Handle<Object> arg2;
|
||||
|
||||
MessageTemplate message =
|
||||
errorMessage ? errorMessage.value()
|
||||
: LookUpErrorMessageForJsonToken(token, arg, arg2, pos);
|
||||
|
||||
Handle<Script> script(factory->NewScript(original_source_));
|
||||
if (isolate()->NeedsSourcePositionsForProfiling()) {
|
||||
@ -290,7 +370,7 @@ void JsonParser<Char>::ReportUnexpectedToken(JsonToken token) {
|
||||
// separated source file.
|
||||
isolate()->debug()->OnCompileError(script);
|
||||
MessageLocation location(script, pos, pos + 1);
|
||||
isolate()->ThrowAt(factory->NewSyntaxError(message, arg1, arg2), &location);
|
||||
isolate()->ThrowAt(factory->NewSyntaxError(message, arg, arg2), &location);
|
||||
|
||||
// Move the cursor to the end so we won't be able to proceed parsing.
|
||||
cursor_ = end_;
|
||||
@ -325,7 +405,9 @@ JsonParser<Char>::~JsonParser() {
|
||||
template <typename Char>
|
||||
MaybeHandle<Object> JsonParser<Char>::ParseJson() {
|
||||
MaybeHandle<Object> result = ParseJsonValue();
|
||||
if (!Check(JsonToken::EOS)) ReportUnexpectedToken(peek());
|
||||
if (!Check(JsonToken::EOS))
|
||||
ReportUnexpectedToken(
|
||||
peek(), MessageTemplate::kJsonParseUnexpectedNonWhiteSpaceCharacter);
|
||||
if (isolate_->has_pending_exception()) return MaybeHandle<Object>();
|
||||
return result;
|
||||
}
|
||||
@ -751,10 +833,12 @@ MaybeHandle<Object> JsonParser<Char>::ParseJsonValue() {
|
||||
property_stack.size());
|
||||
|
||||
// Parse the property key.
|
||||
ExpectNext(JsonToken::STRING);
|
||||
ExpectNext(JsonToken::STRING,
|
||||
MessageTemplate::kJsonParseExpectedPropNameOrRBrace);
|
||||
property_stack.emplace_back(ScanJsonPropertyKey(&cont));
|
||||
|
||||
ExpectNext(JsonToken::COLON);
|
||||
ExpectNext(JsonToken::COLON,
|
||||
MessageTemplate::kJsonParseExpectedColonAfterPropertyName);
|
||||
|
||||
// Continue to start producing the first property value.
|
||||
continue;
|
||||
@ -829,7 +913,9 @@ MaybeHandle<Object> JsonParser<Char>::ParseJsonValue() {
|
||||
|
||||
if (V8_LIKELY(Check(JsonToken::COMMA))) {
|
||||
// Parse the property key.
|
||||
ExpectNext(JsonToken::STRING);
|
||||
ExpectNext(
|
||||
JsonToken::STRING,
|
||||
MessageTemplate::kJsonParseExpectedDoubleQuotedPropertyName);
|
||||
|
||||
property_stack.emplace_back(ScanJsonPropertyKey(&cont));
|
||||
ExpectNext(JsonToken::COLON);
|
||||
@ -855,7 +941,8 @@ MaybeHandle<Object> JsonParser<Char>::ParseJsonValue() {
|
||||
}
|
||||
value = BuildJsonObject(cont, property_stack, feedback);
|
||||
property_stack.resize_no_init(cont.index);
|
||||
Expect(JsonToken::RBRACE);
|
||||
Expect(JsonToken::RBRACE,
|
||||
MessageTemplate::kJsonParseExpectedCommaOrRBrace);
|
||||
|
||||
// Return the object.
|
||||
value = cont.scope.CloseAndEscape(value);
|
||||
@ -874,7 +961,8 @@ MaybeHandle<Object> JsonParser<Char>::ParseJsonValue() {
|
||||
|
||||
value = BuildJsonArray(cont, element_stack);
|
||||
element_stack.resize_no_init(cont.index);
|
||||
Expect(JsonToken::RBRACK);
|
||||
Expect(JsonToken::RBRACK,
|
||||
MessageTemplate::kJsonParseExpectedCommaOrRBrack);
|
||||
|
||||
// Return the array.
|
||||
value = cont.scope.CloseAndEscape(value);
|
||||
@ -933,7 +1021,9 @@ Handle<Object> JsonParser<Char>::ParseJsonNumber() {
|
||||
AdvanceToNonDecimal();
|
||||
if (V8_UNLIKELY(smi_start == cursor_)) {
|
||||
AllowGarbageCollection allow_before_exception;
|
||||
ReportUnexpectedCharacter(CurrentCharacter());
|
||||
ReportUnexpectedToken(
|
||||
JsonToken::ILLEGAL,
|
||||
MessageTemplate::kJsonParseNoNumberAfterMinusSign);
|
||||
return handle(Smi::FromInt(0), isolate_);
|
||||
}
|
||||
c = CurrentCharacter();
|
||||
@ -959,7 +1049,9 @@ Handle<Object> JsonParser<Char>::ParseJsonNumber() {
|
||||
c = NextCharacter();
|
||||
if (!IsDecimalDigit(c)) {
|
||||
AllowGarbageCollection allow_before_exception;
|
||||
ReportUnexpectedCharacter(c);
|
||||
ReportUnexpectedToken(
|
||||
JsonToken::ILLEGAL,
|
||||
MessageTemplate::kJsonParseUnterminatedFractionalNumber);
|
||||
return handle(Smi::FromInt(0), isolate_);
|
||||
}
|
||||
AdvanceToNonDecimal();
|
||||
@ -970,7 +1062,9 @@ Handle<Object> JsonParser<Char>::ParseJsonNumber() {
|
||||
if (c == '-' || c == '+') c = NextCharacter();
|
||||
if (!IsDecimalDigit(c)) {
|
||||
AllowGarbageCollection allow_before_exception;
|
||||
ReportUnexpectedCharacter(c);
|
||||
ReportUnexpectedToken(
|
||||
JsonToken::ILLEGAL,
|
||||
MessageTemplate::kJsonParseExponentPartMissingNumber);
|
||||
return handle(Smi::FromInt(0), isolate_);
|
||||
}
|
||||
AdvanceToNonDecimal();
|
||||
@ -1137,7 +1231,8 @@ JsonString JsonParser<Char>::ScanJsonString(bool needs_internalization) {
|
||||
|
||||
if (V8_UNLIKELY(is_at_end())) {
|
||||
AllowGarbageCollection allow_before_exception;
|
||||
ReportUnexpectedCharacter(kEndOfString);
|
||||
ReportUnexpectedToken(JsonToken::ILLEGAL,
|
||||
MessageTemplate::kJsonParseUnterminatedString);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1188,7 +1283,8 @@ JsonString JsonParser<Char>::ScanJsonString(bool needs_internalization) {
|
||||
|
||||
case EscapeKind::kIllegal:
|
||||
AllowGarbageCollection allow_before_exception;
|
||||
ReportUnexpectedCharacter(c);
|
||||
ReportUnexpectedToken(JsonToken::ILLEGAL,
|
||||
MessageTemplate::kJsonParseBadEscapedCharacter);
|
||||
return JsonString();
|
||||
}
|
||||
|
||||
|
@ -211,17 +211,21 @@ class JsonParser final {
|
||||
advance();
|
||||
}
|
||||
|
||||
void Expect(JsonToken token) {
|
||||
void Expect(JsonToken token,
|
||||
base::Optional<MessageTemplate> errorMessage = base::nullopt) {
|
||||
if (V8_LIKELY(peek() == token)) {
|
||||
advance();
|
||||
} else {
|
||||
ReportUnexpectedToken(peek());
|
||||
errorMessage ? ReportUnexpectedToken(peek(), errorMessage.value())
|
||||
: ReportUnexpectedToken(peek());
|
||||
}
|
||||
}
|
||||
|
||||
void ExpectNext(JsonToken token) {
|
||||
void ExpectNext(
|
||||
JsonToken token,
|
||||
base::Optional<MessageTemplate> errorMessage = base::nullopt) {
|
||||
SkipWhitespace();
|
||||
Expect(token);
|
||||
errorMessage ? Expect(token, errorMessage.value()) : Expect(token);
|
||||
}
|
||||
|
||||
bool Check(JsonToken token) {
|
||||
@ -301,10 +305,22 @@ class JsonParser final {
|
||||
const JsonContinuation& cont,
|
||||
const SmallVector<Handle<Object>>& element_stack);
|
||||
|
||||
static const int kMaxContextCharacters = 10;
|
||||
static const int kMinOriginalSourceLengthForContext =
|
||||
(kMaxContextCharacters * 2) + 1;
|
||||
|
||||
// Mark that a parsing error has happened at the current character.
|
||||
void ReportUnexpectedCharacter(base::uc32 c);
|
||||
bool IsSpecialString();
|
||||
MessageTemplate GetErrorMessageWithEllipses(Handle<Object>& arg,
|
||||
Handle<Object>& arg2, int pos);
|
||||
MessageTemplate LookUpErrorMessageForJsonToken(JsonToken token,
|
||||
Handle<Object>& arg,
|
||||
Handle<Object>& arg2, int pos);
|
||||
// Mark that a parsing error has happened at the current token.
|
||||
void ReportUnexpectedToken(JsonToken token);
|
||||
void ReportUnexpectedToken(
|
||||
JsonToken token,
|
||||
base::Optional<MessageTemplate> errorMessage = base::nullopt);
|
||||
|
||||
inline Isolate* isolate() { return isolate_; }
|
||||
inline Factory* factory() { return isolate_->factory(); }
|
||||
|
@ -6,7 +6,7 @@ Test malformed sourceURL magic comment.
|
||||
columnNumber : 0
|
||||
exception : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -18,7 +18,7 @@ Test malformed sourceURL magic comment.
|
||||
}
|
||||
result : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -32,7 +32,7 @@ Test malformed sourceURL magic comment.
|
||||
columnNumber : 0
|
||||
exception : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//#" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -44,7 +44,7 @@ Test malformed sourceURL magic comment.
|
||||
}
|
||||
result : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//#" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -58,7 +58,7 @@ Test malformed sourceURL magic comment.
|
||||
columnNumber : 0
|
||||
exception : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//# " is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -70,7 +70,7 @@ Test malformed sourceURL magic comment.
|
||||
}
|
||||
result : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//# " is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -84,7 +84,7 @@ Test malformed sourceURL magic comment.
|
||||
columnNumber : 0
|
||||
exception : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//# sourceURL" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -96,7 +96,7 @@ Test malformed sourceURL magic comment.
|
||||
}
|
||||
result : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//# sourceURL" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -110,7 +110,7 @@ Test malformed sourceURL magic comment.
|
||||
columnNumber : 0
|
||||
exception : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//# sourceURL=" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -122,7 +122,7 @@ Test malformed sourceURL magic comment.
|
||||
}
|
||||
result : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//# sourceURL=" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -136,7 +136,7 @@ Test malformed sourceURL magic comment.
|
||||
columnNumber : 0
|
||||
exception : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//# sourceURL="" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
@ -148,10 +148,10 @@ Test malformed sourceURL magic comment.
|
||||
}
|
||||
result : {
|
||||
className : SyntaxError
|
||||
description : SyntaxError: Unexpected token / in JSON at position 0 at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
description : SyntaxError: Unexpected token '/', "//# sourceURL="" is not valid JSON at JSON.parse (<anonymous>) at <anonymous>:1:6
|
||||
objectId : <objectId>
|
||||
subtype : error
|
||||
type : object
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
undefined:1: SyntaxError: Unexpected token / in JSON at position 0
|
||||
undefined:1: SyntaxError: Unexpected token '/', "// Copyrig"... is not valid JSON
|
||||
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
^
|
||||
SyntaxError: Unexpected token / in JSON at position 0
|
||||
SyntaxError: Unexpected token '/', "// Copyrig"... is not valid JSON
|
@ -12,19 +12,19 @@ function TryParse(s, message) {
|
||||
}
|
||||
|
||||
var s = `{"a\\\\b `;
|
||||
TryParse(s, "Unexpected end of JSON input");
|
||||
TryParse(s, "Unterminated string in JSON at position 7");
|
||||
|
||||
var s = `{"a\\\\\u03A9 `;
|
||||
TryParse(s, "Unexpected end of JSON input");
|
||||
TryParse(s, "Unterminated string in JSON at position 7");
|
||||
|
||||
var s = `{"ab `;
|
||||
TryParse(s, "Unexpected end of JSON input");
|
||||
TryParse(s, "Unterminated string in JSON at position 5");
|
||||
|
||||
var s = `{"a\u03A9 `;
|
||||
TryParse(s, "Unexpected end of JSON input");
|
||||
TryParse(s, "Unterminated string in JSON at position 5");
|
||||
|
||||
var s = `{"a\nb":"b"}`;
|
||||
TryParse(s, "Unexpected token \n in JSON at position 3");
|
||||
TryParse(s, "Unexpected token '\n', \"{\"a\nb\":\"b\"}\" is not valid JSON");
|
||||
|
||||
var s = `{"a\nb":"b\u03A9"}`;
|
||||
TryParse(s, "Unexpected token \n in JSON at position 3");
|
||||
TryParse(s, "Unexpected token '\n', \"{\"a\nb\":\"b\u03A9\"}\" is not valid JSON");
|
||||
|
@ -474,25 +474,129 @@ test(function() {
|
||||
eval("'\n'");
|
||||
}, "Invalid or unexpected token", SyntaxError);
|
||||
|
||||
//kJsonParseUnexpectedEOS
|
||||
// kJsonParseUnterminatedString
|
||||
test(function() {
|
||||
JSON.parse('{"a" : "}')
|
||||
}, "Unterminated string in JSON at position 9", SyntaxError);
|
||||
|
||||
// kJsonParseExpectedPropNameOrRBrace
|
||||
test(function() {
|
||||
JSON.parse("{")
|
||||
}, "Unexpected end of JSON input", SyntaxError);
|
||||
}, "Expected property name or '}' in JSON at position 1", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenAt
|
||||
// kJsonParseExpectedDoubleQuotedPropertyName
|
||||
test(function() {
|
||||
JSON.parse('{"foo" : 1, }');
|
||||
}, "Expected double-quoted property name in JSON at position 12", SyntaxError);
|
||||
|
||||
// kJsonParseExpectedCommaNameOrRBrack
|
||||
test(function() {
|
||||
JSON.parse("{'foo': 1}");
|
||||
}, "Expected property name or '}' in JSON at position 1", SyntaxError);
|
||||
|
||||
// kJsonParseExpectedCommaNameOrRBrace
|
||||
test(function() {
|
||||
JSON.parse('[1, 2, 3, 4');
|
||||
}, "Expected ',' or ']' after array element in JSON at position 11", SyntaxError);
|
||||
|
||||
test(function() {
|
||||
JSON.parse('[1, 2, 3, 4g');
|
||||
}, "Expected ',' or ']' after array element in JSON at position 11", SyntaxError);
|
||||
|
||||
// kJsonParseExponentPartMissingNumber
|
||||
test(function() {
|
||||
JSON.parse('[1e]');
|
||||
}, "Exponent part is missing a number in JSON at position 3", SyntaxError);
|
||||
|
||||
// kJsonParseExpectedColonAfterPropertyName
|
||||
test(function() {
|
||||
JSON.parse('{"a"}');
|
||||
}, "Expected ':' after property name in JSON at position 4", SyntaxError);
|
||||
|
||||
// kJsonParseUnterminatedFractionNumber
|
||||
test(function() {
|
||||
JSON.parse('{"a": 0.bs}');
|
||||
}, "Unterminated fractional number in JSON at position 8", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedNonWhiteSpaceCharacter
|
||||
test(function() {
|
||||
JSON.parse('{"a": 3}a');
|
||||
}, "Unexpected non-whitespace character after JSON at position 8", SyntaxError);
|
||||
|
||||
// kJsonParseBadEscapedCharacter
|
||||
test(function() {
|
||||
JSON.parse('{"b" : "\\a"}');
|
||||
}, "Bad escaped character in JSON at position 9", SyntaxError);
|
||||
|
||||
// kJsonParseNoNumberAfterMinusSign
|
||||
test(function() {
|
||||
JSON.parse('-');
|
||||
}, "No number after minus sign in JSON at position 1", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenShortString
|
||||
test(function () {
|
||||
JSON.parse(NaN)
|
||||
}, "\"NaN\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenShortString
|
||||
test(function() {
|
||||
JSON.parse("/")
|
||||
}, "Unexpected token / in JSON at position 0", SyntaxError);
|
||||
}, "Unexpected token '/', \"/\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenNumberAt
|
||||
// kJsonParseUnexpectedTokenShortString
|
||||
test(function () {
|
||||
JSON.parse(undefined)
|
||||
}, "\"undefined\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenShortString
|
||||
test(function () {
|
||||
JSON.parse(Infinity)
|
||||
}, "\"Infinity\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenShortString
|
||||
test(function () {
|
||||
JSON.parse('Bad string')
|
||||
}, "Unexpected token 'B', \"Bad string\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenShortString
|
||||
test(function () {
|
||||
JSON.parse({})
|
||||
}, "\"[object Object]\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseExpectedPropNameOrRBrace
|
||||
test(function() {
|
||||
JSON.parse("{ 1")
|
||||
}, "Unexpected number in JSON at position 2", SyntaxError);
|
||||
}, "Expected property name or '}' in JSON at position 2", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenStringAt
|
||||
// kJsonParseUnexpectedNonWhiteSpaceCharacter
|
||||
test(function() {
|
||||
JSON.parse('"""')
|
||||
}, "Unexpected string in JSON at position 2", SyntaxError);
|
||||
}, "Unexpected non-whitespace character after JSON at position 2", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenStringShortString
|
||||
test(function() {
|
||||
JSON.parse('[1, 2,]');
|
||||
}, "Unexpected token ']', \"[1, 2,]\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenStringShortString
|
||||
test(function() {
|
||||
JSON.parse('[1, 2, 3, 4, ]');
|
||||
}, "Unexpected token ']', \"[1, 2, 3, 4, ]\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenStringSurroundWithContext
|
||||
test(function() {
|
||||
JSON.parse('[1, 2, 3, 4, 5, , 7, 8, 9, 10]');
|
||||
}, "Unexpected token ',', ...\" 3, 4, 5, , 7, 8, 9,\"... is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenStringStartWithContext
|
||||
test(function() {
|
||||
JSON.parse('[, 2, 3, 4, 5, 6, 7, 8, 9, 10]');
|
||||
}, "Unexpected token ',', \"[, 2, 3, 4,\"... is not valid JSON", SyntaxError);
|
||||
|
||||
// kJsonParseUnexpectedTokenStringEndWithContext
|
||||
test(function() {
|
||||
JSON.parse('[1, 2, 3, 4, 5, 6, 7, ]');
|
||||
}, "Unexpected token ']', ...\" 5, 6, 7, ]\" is not valid JSON", SyntaxError);
|
||||
|
||||
// kMalformedRegExp
|
||||
test(function() {
|
||||
|
Loading…
Reference in New Issue
Block a user