Skip to content

Commit

Permalink
Apply review
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 committed Nov 5, 2022
1 parent e549a2f commit 29d520c
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 37 deletions.
63 changes: 37 additions & 26 deletions boa_engine/src/builtins/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,15 @@ impl Eval {
mut strict: bool,
context: &mut Context,
) -> JsResult<JsValue> {
#[derive(Debug, Default)]
#[allow(clippy::struct_excessive_bools)]
/// Flags used to throw early errors on invalid `eval` calls.
struct Flags {
in_function: bool,
in_method: bool,
in_derived_constructor: bool,
in_class_field_initializer: bool,
bitflags::bitflags! {
/// Flags used to throw early errors on invalid `eval` calls.
#[derive(Default)]
struct Flags: u8 {
const IN_FUNCTION = 0b0001;
const IN_METHOD = 0b0010;
const IN_DERIVED_CONSTRUCTOR = 0b0100;
const IN_CLASS_FIELD_INITIALIZER = 0b1000;
}
}

/// Possible actions that can be executed after exiting this function to restore the environment to its
Expand Down Expand Up @@ -143,41 +144,51 @@ impl Eval {
let function_env = function_env.borrow();
// i. Let F be thisEnvRec.[[FunctionObject]].
let function_object = function_env.function_object().borrow();
Flags {
// ii. Set inFunction to true.
in_function: true,
// iii. Set inMethod to thisEnvRec.HasSuperBinding().
in_method: function_env.has_super_binding(),
// iv. If F.[[ConstructorKind]] is derived, set inDerivedConstructor to true.
in_derived_constructor: function_object
.as_function()
.expect("must be function object")
.is_derived_constructor(),
// TODO:
// v. Let classFieldInitializerName be F.[[ClassFieldInitializerName]].
// vi. If classFieldInitializerName is not empty, set inClassFieldInitializer to true.
in_class_field_initializer: false,

// ii. Set inFunction to true.
let mut flags = Flags::IN_FUNCTION;

// iii. Set inMethod to thisEnvRec.HasSuperBinding().
if function_env.has_super_binding() {
flags |= Flags::IN_METHOD;
}

// iv. If F.[[ConstructorKind]] is derived, set inDerivedConstructor to true.
if function_object
.as_function()
.expect("must be function object")
.is_derived_constructor()
{
flags |= Flags::IN_DERIVED_CONSTRUCTOR;
}

// TODO:
// v. Let classFieldInitializerName be F.[[ClassFieldInitializerName]].
// vi. If classFieldInitializerName is not empty, set inClassFieldInitializer to true.

flags
}
_ => Flags::default(),
};

if !flags.in_function && contains(&body, ContainsSymbol::NewTarget) {
if !flags.contains(Flags::IN_FUNCTION) && contains(&body, ContainsSymbol::NewTarget) {
return Err(JsNativeError::syntax()
.with_message("invalid `new.target` expression inside eval")
.into());
}
if !flags.in_method && contains(&body, ContainsSymbol::SuperProperty) {
if !flags.contains(Flags::IN_METHOD) && contains(&body, ContainsSymbol::SuperProperty) {
return Err(JsNativeError::syntax()
.with_message("invalid `super` reference inside eval")
.into());
}
if !flags.in_derived_constructor && contains(&body, ContainsSymbol::SuperCall) {
if !flags.contains(Flags::IN_DERIVED_CONSTRUCTOR)
&& contains(&body, ContainsSymbol::SuperCall)
{
return Err(JsNativeError::syntax()
.with_message("invalid `super` call inside eval")
.into());
}
if flags.in_class_field_initializer && contains_arguments(&body) {
if flags.contains(Flags::IN_CLASS_FIELD_INITIALIZER) && contains_arguments(&body) {
return Err(JsNativeError::syntax()
.with_message("invalid `arguments` reference inside eval")
.into());
Expand Down
3 changes: 0 additions & 3 deletions boa_parser/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ license.workspace = true
repository.workspace = true
rust-version.workspace = true

[features]
# serde = ["boa_interner/serde", "dep:serde"]

[dependencies]
boa_interner.workspace = true
boa_macros.workspace = true
Expand Down
11 changes: 9 additions & 2 deletions boa_parser/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
//! Syntactical analysis, such as Parsing and Lexing.
// syntax module has a lot of acronyms
//! Parser targeting the latest [ECMAScript language specification][spec].
//!
//! This crate contains implementations of a [`Lexer`] and a [`Parser`] for the **ECMAScript**
//! language. The [lexical grammar][lex] and the [syntactic grammar][grammar] being targeted are
//! fully defined in the specification. See the links provided for more information.
//!
//! [spec]: https://tc39.es/ecma262
//! [lex]: https://tc39.es/ecma262/#sec-ecmascript-language-lexical-grammar
//! [grammar]: https://tc39.es/ecma262/#sec-ecmascript-language-expressions

#![cfg_attr(not(test), forbid(clippy::unwrap_used))]
#![warn(
Expand Down
29 changes: 23 additions & 6 deletions boa_parser/src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ where
struct AllowYield(bool);

impl From<bool> for AllowYield {
#[inline]
fn from(allow: bool) -> Self {
Self(allow)
}
Expand All @@ -63,6 +64,7 @@ impl From<bool> for AllowYield {
struct AllowAwait(bool);

impl From<bool> for AllowAwait {
#[inline]
fn from(allow: bool) -> Self {
Self(allow)
}
Expand All @@ -73,6 +75,7 @@ impl From<bool> for AllowAwait {
struct AllowIn(bool);

impl From<bool> for AllowIn {
#[inline]
fn from(allow: bool) -> Self {
Self(allow)
}
Expand All @@ -83,6 +86,7 @@ impl From<bool> for AllowIn {
struct AllowReturn(bool);

impl From<bool> for AllowReturn {
#[inline]
fn from(allow: bool) -> Self {
Self(allow)
}
Expand All @@ -93,11 +97,21 @@ impl From<bool> for AllowReturn {
struct AllowDefault(bool);

impl From<bool> for AllowDefault {
#[inline]
fn from(allow: bool) -> Self {
Self(allow)
}
}

/// Parser for the ECMAScript language.
///
/// This parser implementation tries to be conformant to the most recent
/// [ECMAScript language specification], and it also implements some legacy features like
/// [labelled functions][label] or [duplicated block-level function definitions][block].
///
/// [spec]: https://tc39.es/ecma262/#sec-ecmascript-language-source-code
/// [label]: https://tc39.es/ecma262/#sec-labelled-function-declarations
/// [block]: https://tc39.es/ecma262/#sec-block-duplicates-allowed-static-semantics
#[derive(Debug)]
pub struct Parser<R> {
/// Cursor of the parser, pointing to the lexer and used to get tokens for the parser.
Expand All @@ -106,6 +120,7 @@ pub struct Parser<R> {

impl<R> Parser<R> {
/// Create a new `Parser` with a reader as the input to parse.
#[inline]
pub fn new(reader: R) -> Self
where
R: Read,
Expand All @@ -116,6 +131,7 @@ impl<R> Parser<R> {
}

/// Set the parser strict mode to true.
#[inline]
pub fn set_strict(&mut self)
where
R: Read,
Expand All @@ -131,6 +147,7 @@ impl<R> Parser<R> {
/// Will return `Err` on any parsing error, including invalid reads of the bytes being parsed.
///
/// [spec]: https://tc39.es/ecma262/#prod-Script
#[inline]
pub fn parse_all(&mut self, interner: &mut Interner) -> Result<StatementList, Error>
where
R: Read,
Expand All @@ -147,6 +164,7 @@ impl<R> Parser<R> {
/// Will return `Err` on any parsing error, including invalid reads of the bytes being parsed.
///
/// [spec]: https://tc39.es/ecma262/#sec-performeval
#[inline]
pub fn parse_eval(
&mut self,
direct: bool,
Expand All @@ -155,12 +173,6 @@ impl<R> Parser<R> {
where
R: Read,
{
// 5. Perform ? HostEnsureCanCompileStrings(evalRealm).
// 11. Perform the following substeps in an implementation-defined order, possibly interleaving parsing and error detection:
// a. Let script be ParseText(StringToCodePoints(x), Script).
// b. If script is a List of errors, throw a SyntaxError exception.
// c. If script Contains ScriptBody is false, return undefined.
// d. Let body be the ScriptBody of script.
Script::new(direct).parse(&mut self.cursor, interner)
}

Expand All @@ -171,6 +183,7 @@ impl<R> Parser<R> {
/// Will return `Err` on any parsing error, including invalid reads of the bytes being parsed.
///
/// [spec]: https://tc39.es/ecma262/#prod-FunctionBody
#[inline]
pub fn parse_function_body(
&mut self,
interner: &mut Interner,
Expand All @@ -190,6 +203,7 @@ impl<R> Parser<R> {
/// Will return `Err` on any parsing error, including invalid reads of the bytes being parsed.
///
/// [spec]: https://tc39.es/ecma262/#prod-FormalParameterList
#[inline]
pub fn parse_formal_parameters(
&mut self,
interner: &mut Interner,
Expand All @@ -216,6 +230,7 @@ pub struct Script {

impl Script {
/// Create a new `Script` parser.
#[inline]
fn new(direct_eval: bool) -> Self {
Self { direct_eval }
}
Expand Down Expand Up @@ -290,6 +305,7 @@ pub struct ScriptBody {

impl ScriptBody {
/// Create a new `ScriptBody` parser.
#[inline]
fn new(direct_eval: bool) -> Self {
Self { direct_eval }
}
Expand Down Expand Up @@ -328,6 +344,7 @@ where
}

/// Helper to check if any parameter names are declared in the given list.
#[inline]
fn name_in_lexically_declared_names(
bound_names: &[Identifier],
lexical_names: &[Identifier],
Expand Down

0 comments on commit 29d520c

Please sign in to comment.