Skip to content

Commit

Permalink
Fix remaining static module bugs (#2955)
Browse files Browse the repository at this point in the history
* Fix remaining module bugs

* npx prettier

* Fix regression
  • Loading branch information
jedel1043 committed May 24, 2023
1 parent 8753406 commit 9bbe018
Show file tree
Hide file tree
Showing 18 changed files with 319 additions and 142 deletions.
20 changes: 19 additions & 1 deletion .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,32 @@
{
"type": "lldb",
"request": "launch",
"name": "Launch",
"name": "Launch (Script)",
"windows": {
"program": "${workspaceFolder}/target/debug/boa.exe"
},
"program": "${workspaceFolder}/target/debug/boa",
"args": ["${workspaceFolder}/tests/js/test.js", "--debug-object"],
"sourceLanguages": ["rust"],
"preLaunchTask": "Cargo Build"
},
{
"type": "lldb",
"request": "launch",
"name": "Launch (Module)",
"windows": {
"program": "${workspaceFolder}/target/debug/boa.exe"
},
"program": "${workspaceFolder}/target/debug/boa",
"args": [
"${workspaceFolder}/tests/js/test.js",
"--debug-object",
"-m",
"-r",
"tests/js"
],
"sourceLanguages": ["rust"],
"preLaunchTask": "Cargo Build"
}
]
}
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions boa_ast/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ bitflags = "2.3.1"
num-bigint = "0.4.3"
serde = { version = "1.0.163", features = ["derive"], optional = true }
arbitrary = { version = "1", features = ["derive"], optional = true }
indexmap = "1.9.3"
11 changes: 10 additions & 1 deletion boa_ast/src/declaration/export.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,16 +174,18 @@ impl VisitWith for ExportDeclaration {
pub struct ExportSpecifier {
alias: Sym,
private_name: Sym,
string_literal: bool,
}

impl ExportSpecifier {
/// Creates a new [`ExportSpecifier`].
#[inline]
#[must_use]
pub const fn new(alias: Sym, private_name: Sym) -> Self {
pub const fn new(alias: Sym, private_name: Sym, string_literal: bool) -> Self {
Self {
alias,
private_name,
string_literal,
}
}

Expand All @@ -200,6 +202,13 @@ impl ExportSpecifier {
pub const fn private_name(self) -> Sym {
self.private_name
}

/// Returns `true` if the private name of the specifier was a `StringLiteral`.
#[inline]
#[must_use]
pub const fn string_literal(&self) -> bool {
self.string_literal
}
}

impl VisitWith for ExportSpecifier {
Expand Down
11 changes: 6 additions & 5 deletions boa_ast/src/module_item_list/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
//!
//! [spec]: https://tc39.es/ecma262/#sec-modules

use std::{convert::Infallible, ops::ControlFlow};
use std::{convert::Infallible, hash::BuildHasherDefault, ops::ControlFlow};

use boa_interner::Sym;
use rustc_hash::FxHashSet;
use indexmap::IndexSet;
use rustc_hash::{FxHashSet, FxHasher};

use crate::{
declaration::{
Expand Down Expand Up @@ -205,9 +206,9 @@ impl ModuleItemList {
/// [spec]: https://tc39.es/ecma262/#sec-static-semantics-modulerequests
#[inline]
#[must_use]
pub fn requests(&self) -> FxHashSet<Sym> {
pub fn requests(&self) -> IndexSet<Sym, BuildHasherDefault<FxHasher>> {
#[derive(Debug)]
struct RequestsVisitor<'vec>(&'vec mut FxHashSet<Sym>);
struct RequestsVisitor<'vec>(&'vec mut IndexSet<Sym, BuildHasherDefault<FxHasher>>);

impl<'ast> Visitor<'ast> for RequestsVisitor<'_> {
type BreakTy = Infallible;
Expand All @@ -227,7 +228,7 @@ impl ModuleItemList {
}
}

let mut requests = FxHashSet::default();
let mut requests = IndexSet::default();

RequestsVisitor(&mut requests).visit_module_item_list(self);

Expand Down
10 changes: 5 additions & 5 deletions boa_engine/src/bytecompiler/declarations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,16 +351,16 @@ impl ByteCompiler<'_, '_> {
for d in &declarations {
match d {
LexicallyScopedDeclaration::Function(function) => {
self.function(function.into(), NodeKind::Declaration, false);
self.function_with_binding(function.into(), NodeKind::Declaration, false);
}
LexicallyScopedDeclaration::Generator(function) => {
self.function(function.into(), NodeKind::Declaration, false);
self.function_with_binding(function.into(), NodeKind::Declaration, false);
}
LexicallyScopedDeclaration::AsyncFunction(function) => {
self.function(function.into(), NodeKind::Declaration, false);
self.function_with_binding(function.into(), NodeKind::Declaration, false);
}
LexicallyScopedDeclaration::AsyncGenerator(function) => {
self.function(function.into(), NodeKind::Declaration, false);
self.function_with_binding(function.into(), NodeKind::Declaration, false);
}
_ => {}
}
Expand Down Expand Up @@ -1147,7 +1147,7 @@ impl ByteCompiler<'_, '_> {
// a. Let fn be the sole element of the BoundNames of f.
// b. Let fo be InstantiateFunctionObject of f with arguments lexEnv and privateEnv.
// c. Perform ! varEnv.SetMutableBinding(fn, fo, false).
self.function(function, NodeKind::Declaration, false);
self.function_with_binding(function, NodeKind::Declaration, false);
}

// 37. Return unused.
Expand Down
2 changes: 1 addition & 1 deletion boa_engine/src/bytecompiler/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ impl ByteCompiler<'_, '_> {
.create_mutable_binding(name, function_scope));
}

/// Initialize a mutable binding at bytecode compile time and return it's binding locator.
/// Initialize a mutable binding at bytecode compile time and return its binding locator.
pub(crate) fn initialize_mutable_binding(
&self,
name: Identifier,
Expand Down
12 changes: 6 additions & 6 deletions boa_engine/src/bytecompiler/expression/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,22 +124,22 @@ impl ByteCompiler<'_, '_> {
}
Expression::Spread(spread) => self.compile_expr(spread.target(), true),
Expression::Function(function) => {
self.function(function.into(), NodeKind::Expression, use_expr);
self.function_with_binding(function.into(), NodeKind::Expression, use_expr);
}
Expression::ArrowFunction(function) => {
self.function(function.into(), NodeKind::Expression, use_expr);
self.function_with_binding(function.into(), NodeKind::Expression, use_expr);
}
Expression::AsyncArrowFunction(function) => {
self.function(function.into(), NodeKind::Expression, use_expr);
self.function_with_binding(function.into(), NodeKind::Expression, use_expr);
}
Expression::Generator(function) => {
self.function(function.into(), NodeKind::Expression, use_expr);
self.function_with_binding(function.into(), NodeKind::Expression, use_expr);
}
Expression::AsyncFunction(function) => {
self.function(function.into(), NodeKind::Expression, use_expr);
self.function_with_binding(function.into(), NodeKind::Expression, use_expr);
}
Expression::AsyncGenerator(function) => {
self.function(function.into(), NodeKind::Expression, use_expr);
self.function_with_binding(function.into(), NodeKind::Expression, use_expr);
}
Expression::Call(call) => self.call(Callable::Call(call), use_expr),
Expression::New(new) => self.call(Callable::New(new), use_expr),
Expand Down
86 changes: 48 additions & 38 deletions boa_engine/src/bytecompiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub(crate) enum NodeKind {

/// Describes the type of a function.
#[derive(Debug, Clone, Copy, PartialEq)]
enum FunctionKind {
pub(crate) enum FunctionKind {
Ordinary,
Arrow,
AsyncArrow,
Expand All @@ -57,37 +57,31 @@ enum FunctionKind {
AsyncGenerator,
}

impl FunctionKind {
pub(crate) const fn is_arrow(self) -> bool {
matches!(self, Self::Arrow | Self::AsyncArrow)
}

pub(crate) const fn is_async(self) -> bool {
matches!(self, Self::Async | Self::AsyncGenerator | Self::AsyncArrow)
}

pub(crate) const fn is_generator(self) -> bool {
matches!(self, Self::Generator | Self::AsyncGenerator)
}
}

/// Describes the complete specification of a function node.
#[derive(Debug, Clone, Copy, PartialEq)]
#[allow(single_use_lifetimes)]
pub(crate) struct FunctionSpec<'a> {
kind: FunctionKind,
pub(crate) kind: FunctionKind,
pub(crate) name: Option<Identifier>,
parameters: &'a FormalParameterList,
body: &'a FunctionBody,
has_binding_identifier: bool,
}

impl FunctionSpec<'_> {
const fn is_arrow(&self) -> bool {
matches!(self.kind, FunctionKind::Arrow | FunctionKind::AsyncArrow)
}

const fn is_async(&self) -> bool {
matches!(
self.kind,
FunctionKind::Async | FunctionKind::AsyncGenerator | FunctionKind::AsyncArrow
)
}

const fn is_generator(&self) -> bool {
matches!(
self.kind,
FunctionKind::Generator | FunctionKind::AsyncGenerator
)
}
}

impl<'a> From<&'a Function> for FunctionSpec<'a> {
fn from(function: &'a Function) -> Self {
FunctionSpec {
Expand Down Expand Up @@ -1070,17 +1064,13 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
}
}

/// Compile a function AST Node into bytecode.
pub(crate) fn function(
&mut self,
function: FunctionSpec<'_>,
node_kind: NodeKind,
use_expr: bool,
) {
/// Compiles a function AST Node into bytecode, and returns its index into
/// the `functions` array.
pub(crate) fn function(&mut self, function: FunctionSpec<'_>) -> u32 {
let (generator, r#async, arrow) = (
function.is_generator(),
function.is_async(),
function.is_arrow(),
function.kind.is_generator(),
function.kind.is_async(),
function.kind.is_arrow(),
);
let FunctionSpec {
name,
Expand Down Expand Up @@ -1117,6 +1107,26 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
let index = self.functions.len() as u32;
self.functions.push(code);

index
}

/// Compiles a function AST Node into bytecode, setting its corresponding binding or
/// pushing it to the stack if necessary.
pub(crate) fn function_with_binding(
&mut self,
function: FunctionSpec<'_>,
node_kind: NodeKind,
use_expr: bool,
) {
let name = function.name;
let (generator, r#async, arrow) = (
function.kind.is_generator(),
function.kind.is_async(),
function.kind.is_arrow(),
);

let index = self.function(function);

if r#async && generator {
self.emit(Opcode::GetGeneratorAsync, &[index]);
} else if generator {
Expand Down Expand Up @@ -1152,9 +1162,9 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
/// Compile an object method AST Node into bytecode.
pub(crate) fn object_method(&mut self, function: FunctionSpec<'_>) {
let (generator, r#async, arrow) = (
function.is_generator(),
function.is_async(),
function.is_arrow(),
function.kind.is_generator(),
function.kind.is_async(),
function.kind.is_arrow(),
);
let FunctionSpec {
name,
Expand Down Expand Up @@ -1212,9 +1222,9 @@ impl<'ctx, 'host> ByteCompiler<'ctx, 'host> {
/// Compile a class method AST Node into bytecode.
fn method(&mut self, function: FunctionSpec<'_>, class_name: Sym) {
let (generator, r#async, arrow) = (
function.is_generator(),
function.is_async(),
function.is_arrow(),
function.kind.is_generator(),
function.kind.is_async(),
function.kind.is_arrow(),
);
let FunctionSpec {
name,
Expand Down
16 changes: 14 additions & 2 deletions boa_engine/src/bytecompiler/module.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::vm::BindingOpcode;
use crate::vm::{BindingOpcode, Opcode};

use super::ByteCompiler;
use super::{ByteCompiler, Literal};
use boa_ast::{declaration::ExportDeclaration, expression::Identifier, ModuleItem, ModuleItemList};
use boa_interner::Sym;

Expand Down Expand Up @@ -55,6 +55,18 @@ impl ByteCompiler<'_, '_> {
let name = Identifier::from(Sym::DEFAULT_EXPORT);
self.create_mutable_binding(name, false);
self.compile_expr(expr, true);

if expr.is_anonymous_function_definition() {
let default = self
.interner()
.resolve_expect(Sym::DEFAULT)
.into_common(false);
self.emit_push_literal(Literal::String(default));
self.emit_opcode(Opcode::Swap);
self.emit_opcode(Opcode::SetFunctionName);
self.emit_u8(0);
}

self.emit_binding(BindingOpcode::InitLet, name);
}
}
Expand Down
2 changes: 1 addition & 1 deletion boa_engine/src/bytecompiler/statement/labelled.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl ByteCompiler<'_, '_> {
stmt => self.compile_stmt(stmt, use_expr),
},
LabelledItem::Function(f) => {
self.function(f.into(), NodeKind::Declaration, false);
self.function_with_binding(f.into(), NodeKind::Declaration, false);
}
}

Expand Down

0 comments on commit 9bbe018

Please sign in to comment.