mirror of
https://github.com/RGBCube/serenity
synced 2025-05-20 14:55:08 +00:00
LibJS: Unprefixed octal numbers are a syntax error in strict mode
This commit is contained in:
parent
602eb98479
commit
46cc1f718e
4 changed files with 24 additions and 4 deletions
|
@ -422,8 +422,7 @@ Token Lexer::next()
|
||||||
consume();
|
consume();
|
||||||
token_type = TokenType::BigIntLiteral;
|
token_type = TokenType::BigIntLiteral;
|
||||||
} else if (isdigit(m_current_char)) {
|
} else if (isdigit(m_current_char)) {
|
||||||
// octal without 'O' prefix. Forbidden in 'strict mode'
|
// octal without '0o' prefix. Forbidden in 'strict mode'
|
||||||
// FIXME: We need to make sure this produces a syntax error when in strict mode
|
|
||||||
do {
|
do {
|
||||||
consume();
|
consume();
|
||||||
} while (isdigit(m_current_char));
|
} while (isdigit(m_current_char));
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include <AK/ScopeGuard.h>
|
#include <AK/ScopeGuard.h>
|
||||||
#include <AK/StdLibExtras.h>
|
#include <AK/StdLibExtras.h>
|
||||||
#include <AK/TemporaryChange.h>
|
#include <AK/TemporaryChange.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
|
||||||
namespace JS {
|
namespace JS {
|
||||||
|
|
||||||
|
@ -591,7 +592,7 @@ NonnullRefPtr<Expression> Parser::parse_primary_expression()
|
||||||
return create_ast_node<Identifier>(consume().value());
|
return create_ast_node<Identifier>(consume().value());
|
||||||
}
|
}
|
||||||
case TokenType::NumericLiteral:
|
case TokenType::NumericLiteral:
|
||||||
return create_ast_node<NumericLiteral>(consume().double_value());
|
return create_ast_node<NumericLiteral>(consume_and_validate_numeric_literal().double_value());
|
||||||
case TokenType::BigIntLiteral:
|
case TokenType::BigIntLiteral:
|
||||||
return create_ast_node<BigIntLiteral>(consume().value());
|
return create_ast_node<BigIntLiteral>(consume().value());
|
||||||
case TokenType::BoolLiteral:
|
case TokenType::BoolLiteral:
|
||||||
|
@ -687,7 +688,8 @@ NonnullRefPtr<Expression> Parser::parse_property_key()
|
||||||
if (match(TokenType::StringLiteral)) {
|
if (match(TokenType::StringLiteral)) {
|
||||||
return parse_string_literal(consume());
|
return parse_string_literal(consume());
|
||||||
} else if (match(TokenType::NumericLiteral)) {
|
} else if (match(TokenType::NumericLiteral)) {
|
||||||
return create_ast_node<StringLiteral>(consume(TokenType::NumericLiteral).value());
|
// FIXME: "evaluate" key to double value, see https://github.com/SerenityOS/serenity/issues/3717
|
||||||
|
return create_ast_node<StringLiteral>(consume_and_validate_numeric_literal().value());
|
||||||
} else if (match(TokenType::BigIntLiteral)) {
|
} else if (match(TokenType::BigIntLiteral)) {
|
||||||
auto value = consume(TokenType::BigIntLiteral).value();
|
auto value = consume(TokenType::BigIntLiteral).value();
|
||||||
return create_ast_node<StringLiteral>(value.substring_view(0, value.length() - 1));
|
return create_ast_node<StringLiteral>(value.substring_view(0, value.length() - 1));
|
||||||
|
@ -1831,6 +1833,19 @@ Token Parser::consume(TokenType expected_type)
|
||||||
return consume();
|
return consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Token Parser::consume_and_validate_numeric_literal()
|
||||||
|
{
|
||||||
|
auto is_unprefixed_octal_number = [](const StringView& value) {
|
||||||
|
return value.length() > 1 && value[0] == '0' && isdigit(value[1]);
|
||||||
|
};
|
||||||
|
auto literal_start_line = m_parser_state.m_current_token.line_number();
|
||||||
|
auto literal_start_column = m_parser_state.m_current_token.line_column();
|
||||||
|
auto token = consume(TokenType::NumericLiteral);
|
||||||
|
if (m_parser_state.m_strict_mode && is_unprefixed_octal_number(token.value()))
|
||||||
|
syntax_error("Unprefixed octal number not allowed in strict mode", literal_start_line, literal_start_column);
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
void Parser::expected(const char* what)
|
void Parser::expected(const char* what)
|
||||||
{
|
{
|
||||||
syntax_error(String::formatted("Unexpected token {}. Expected {}", m_parser_state.m_current_token.name(), what));
|
syntax_error(String::formatted("Unexpected token {}. Expected {}", m_parser_state.m_current_token.name(), what));
|
||||||
|
|
|
@ -139,6 +139,7 @@ private:
|
||||||
void syntax_error(const String& message, size_t line = 0, size_t column = 0);
|
void syntax_error(const String& message, size_t line = 0, size_t column = 0);
|
||||||
Token consume();
|
Token consume();
|
||||||
Token consume(TokenType type);
|
Token consume(TokenType type);
|
||||||
|
Token consume_and_validate_numeric_literal();
|
||||||
void consume_or_insert_semicolon();
|
void consume_or_insert_semicolon();
|
||||||
void save_state();
|
void save_state();
|
||||||
void load_state();
|
void load_state();
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// FIXME: Some of the test cases below are duplicated, presumably to test
|
||||||
|
// uppercase as well which then got lowercased by Prettier at some point.
|
||||||
|
|
||||||
test("hex literals", () => {
|
test("hex literals", () => {
|
||||||
expect(0xff).toBe(255);
|
expect(0xff).toBe(255);
|
||||||
expect(0xff).toBe(255);
|
expect(0xff).toBe(255);
|
||||||
|
@ -6,6 +9,7 @@ test("hex literals", () => {
|
||||||
test("octal literals", () => {
|
test("octal literals", () => {
|
||||||
expect(0o10).toBe(8);
|
expect(0o10).toBe(8);
|
||||||
expect(0o10).toBe(8);
|
expect(0o10).toBe(8);
|
||||||
|
expect(010).toBe(8);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("binary literals", () => {
|
test("binary literals", () => {
|
||||||
|
@ -41,4 +45,5 @@ test("invalid numeric literals", () => {
|
||||||
expect("0x").not.toEval();
|
expect("0x").not.toEval();
|
||||||
expect("0b").not.toEval();
|
expect("0b").not.toEval();
|
||||||
expect("0o").not.toEval();
|
expect("0o").not.toEval();
|
||||||
|
expect("'use strict'; 0755").not.toEval();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue