1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 01:07:36 +00:00

LibJS: Parse RegExp literals at AST creation time, not execution time

The spec requires that invalid RegExp literals must cause a Syntax Error
before the JavaScript is executed. See:
https://tc39.es/ecma262/#sec-patterns-static-semantics-early-errors

This is explicitly tested in the RegExp/property-escapes test262 tests.
For example, see unsupported-property-Line_Break.js:

    $DONOTEVALUATE();
    /\p{Line_Break}/u;

That RegExp literal is invalid because Line_Break is not a supported
Unicode property. $DONOTEVALUATE() just throws an exception when it is
executed. The test expects that this file will fail to be parsed.

Note that RegExp patterns can still be parsed at execution time by way
of "new RegExp(...)".
This commit is contained in:
Timothy Flynn 2021-07-29 10:34:37 -04:00 committed by Linus Groh
parent 1400e3cf58
commit f1dd770a8a
6 changed files with 124 additions and 94 deletions

View file

@ -19,6 +19,7 @@
#include <LibJS/Runtime/PropertyName.h>
#include <LibJS/Runtime/Value.h>
#include <LibJS/SourceRange.h>
#include <LibRegex/Regex.h>
namespace JS {
@ -758,8 +759,11 @@ public:
class RegExpLiteral final : public Literal {
public:
explicit RegExpLiteral(SourceRange source_range, String pattern, String flags)
RegExpLiteral(SourceRange source_range, regex::Parser::Result parsed_regex, String parsed_pattern, regex::RegexOptions<ECMAScriptFlags> parsed_flags, String pattern, String flags)
: Literal(source_range)
, m_parsed_regex(move(parsed_regex))
, m_parsed_pattern(move(parsed_pattern))
, m_parsed_flags(move(parsed_flags))
, m_pattern(move(pattern))
, m_flags(move(flags))
{
@ -769,10 +773,16 @@ public:
virtual void dump(int indent) const override;
virtual void generate_bytecode(Bytecode::Generator&) const override;
regex::Parser::Result const& parsed_regex() const { return m_parsed_regex; }
String const& parsed_pattern() const { return m_parsed_pattern; }
regex::RegexOptions<ECMAScriptFlags> const& parsed_flags() const { return m_parsed_flags; }
String const& pattern() const { return m_pattern; }
String const& flags() const { return m_flags; }
private:
regex::Parser::Result m_parsed_regex;
String m_parsed_pattern;
regex::RegexOptions<ECMAScriptFlags> m_parsed_flags;
String m_pattern;
String m_flags;
};