Browse Source

Improve CI testing (#3333)

* Improve CI testing

* Bail on error

* cargo fmt

* Invert names

* Split misc action

* Rename some actions
pull/3337/head
José Julián Espina 12 months ago committed by GitHub
parent
commit
d8f6834d5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 133
      .github/workflows/rust.yml
  2. 1
      Cargo.lock
  3. 2
      Cargo.toml
  4. 2
      boa_ast/Cargo.toml
  5. 21
      boa_cli/src/main.rs
  6. 2
      boa_engine/Cargo.toml
  7. 2
      boa_engine/src/vm/mod.rs
  8. 8
      boa_engine/src/vm/opcode/mod.rs
  9. 1
      boa_examples/Cargo.toml
  10. 3
      boa_examples/src/bin/commuter_visitor.rs
  11. 59
      boa_examples/src/bin/jsdate.rs
  12. 42
      boa_examples/src/bin/loadfile.rs
  13. 67
      boa_examples/src/bin/modulehandler.rs
  14. 4
      boa_examples/src/bin/modules.rs
  15. 8
      boa_examples/src/bin/runtime_limits.rs
  16. 3
      boa_examples/src/bin/symbol_visitor.rs
  17. 6
      boa_interner/Cargo.toml
  18. 1
      boa_runtime/src/console/mod.rs
  19. 57
      fuzz/Cargo.lock

133
.github/workflows/rust.yml

@ -10,6 +10,9 @@ on:
merge_group: merge_group:
types: [checks_requested] types: [checks_requested]
env:
RUSTFLAGS: -Dwarnings
jobs: jobs:
coverage: coverage:
name: Coverage name: Coverage
@ -38,7 +41,7 @@ jobs:
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v3
tests: tests:
name: Build and Test name: Test
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
timeout-minutes: 60 timeout-minutes: 60
strategy: strategy:
@ -58,24 +61,16 @@ jobs:
run: cargo test --no-run --profile ci run: cargo test --no-run --profile ci
# this order is faster according to rust-analyzer # this order is faster according to rust-analyzer
- name: Build - name: Build
run: cargo build --all-targets --quiet --profile ci run: cargo build --all-targets --quiet --profile ci --features annex-b,intl,experimental
- name: Install latest nextest - name: Install latest nextest
uses: taiki-e/install-action@nextest uses: taiki-e/install-action@nextest
- name: Test with nextest - name: Test with nextest
run: cargo nextest run --profile ci --cargo-profile ci --features annex-b,intl,experimental run: cargo nextest run --profile ci --cargo-profile ci --features annex-b,intl,experimental
- name: Test docs - name: Test docs
run: cargo test --doc --profile ci --features annex-b,intl,experimental run: cargo test --doc --profile ci --features annex-b,intl,experimental
- name: Build boa_ast crate
run: cargo build -p boa_ast
- name: Build boa_cli crate
run: cargo build -p boa_cli
- name: Build boa_parser crate
run: cargo build -p boa_parser
- name: Build boa_runtime crate
run: cargo build -p boa_runtime
msrv: msrv:
name: Minimum supported Rust version name: MSRV
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
@ -92,12 +87,51 @@ jobs:
- name: Check compilation - name: Check compilation
run: cargo check --all-features --all-targets run: cargo check --all-features --all-targets
misc: fmt:
name: Misc name: Formatting
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1.0.7
with:
toolchain: stable
override: true
profile: minimal
components: rustfmt
- name: Format (rustfmt)
run: cargo fmt --all --check
clippy:
name: Lint
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1.0.7
with:
toolchain: stable
override: true
profile: minimal
components: clippy
- name: Install cargo-workspaces
uses: actions-rs/install@v0.1
with:
crate: cargo-workspaces
- uses: Swatinem/rust-cache@v2
with:
key: clippy
- name: Clippy (All features)
run: cargo workspaces exec cargo clippy --all-features --all-targets -- -D warnings
- name: Clippy (No features)
run: cargo workspaces exec cargo clippy --no-default-features --all-targets -- -D warnings
docs:
name: Documentation
runs-on: ubuntu-latest runs-on: ubuntu-latest
timeout-minutes: 60 timeout-minutes: 60
env: env:
RUSTFLAGS: -D warnings RUSTDOCFLAGS: -D warnings
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1.0.7 - uses: actions-rs/toolchain@v1.0.7
@ -105,28 +139,61 @@ jobs:
toolchain: stable toolchain: stable
override: true override: true
profile: minimal profile: minimal
components: rustfmt, clippy - uses: Swatinem/rust-cache@v2
- uses: actions-rs/install@v0.1 with:
key: docs
- name: Generate documentation
run: cargo doc -v --document-private-items --all-features
build-fuzz:
name: Fuzzing
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1.0.7
with:
toolchain: stable
override: true
profile: minimal
- name: Install cargo-fuzz
uses: actions-rs/install@v0.1
with: with:
crate: cargo-fuzz crate: cargo-fuzz
version: latest version: latest
- uses: Swatinem/rust-cache@v2 - uses: Swatinem/rust-cache@v2
with: with:
key: misc key: build-fuzz
- name: Format (rustfmt) - name: Build fuzz
run: cargo fmt --all --check
- name: Lint (All features)
run: cargo clippy --all-features --all-targets
- name: Lint (No features)
run: cargo clippy -p boa_engine --no-default-features --all-targets
- name: Generate documentation
run: cargo doc -v --document-private-items --all-features
- name: Build
run: cargo build --all-targets --quiet --profile ci
- name: Build fuzzers
run: cargo fuzz build -s none run: cargo fuzz build -s none
- run: cd boa_examples
- name: Build examples build-run-examples:
run: cargo build --quiet --profile ci name: Build & run examples
- name: Run example classes runs-on: ubuntu-latest
run: cargo run --bin classes --profile ci timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- uses: actions-rs/toolchain@v1.0.7
with:
toolchain: stable
override: true
profile: minimal
- name: Install cargo-workspaces
uses: actions-rs/install@v0.1
with:
crate: cargo-workspaces
- uses: Swatinem/rust-cache@v2
with:
key: build-run-examples
- name: Build (All features)
run: cargo workspaces exec cargo build --all-features --all-targets --profile ci
- name: Build (No features)
run: cargo workspaces exec cargo build --no-default-features --all-targets --profile ci
- name: Run examples
run: |
cd boa_examples
cargo run -p boa_examples --bin 2>&1 \
| grep -E '^ ' \
| xargs -n1 sh -c 'cargo run -p boa_examples --profile ci --bin $0 || exit 255'

1
Cargo.lock generated

@ -420,6 +420,7 @@ dependencies = [
"boa_interner", "boa_interner",
"boa_parser", "boa_parser",
"boa_runtime", "boa_runtime",
"chrono",
"futures-util", "futures-util",
"smol", "smol",
] ]

2
Cargo.toml

@ -47,7 +47,7 @@ clap = "4.4.6"
colored = "2.0.4" colored = "2.0.4"
fast-float = "0.2.0" fast-float = "0.2.0"
hashbrown = { version = "0.14.1", default-features = false } hashbrown = { version = "0.14.1", default-features = false }
indexmap = "2.0.1" indexmap = { version = "2.0.1", default-features = false }
indoc = "2.0.4" indoc = "2.0.4"
jemallocator = "0.5.4" jemallocator = "0.5.4"
num-bigint = "0.4.4" num-bigint = "0.4.4"

2
boa_ast/Cargo.toml

@ -11,7 +11,7 @@ repository.workspace = true
rust-version.workspace = true rust-version.workspace = true
[features] [features]
serde = ["dep:serde", "boa_interner/serde", "bitflags/serde"] serde = ["dep:serde", "boa_interner/serde", "bitflags/serde", "num-bigint/serde"]
arbitrary = ["dep:arbitrary", "boa_interner/arbitrary", "num-bigint/arbitrary"] arbitrary = ["dep:arbitrary", "boa_interner/arbitrary", "num-bigint/arbitrary"]
[dependencies] [dependencies]

21
boa_cli/src/main.rs

@ -59,9 +59,11 @@
clippy::pedantic, clippy::pedantic,
clippy::nursery, clippy::nursery,
)] )]
#![allow(clippy::option_if_let_else, clippy::redundant_pub_crate)] #![allow(
unused_crate_dependencies,
use boa_ast as _; clippy::option_if_let_else,
clippy::redundant_pub_crate
)]
mod debug; mod debug;
mod helper; mod helper;
@ -88,16 +90,21 @@ use std::{
println, println,
}; };
#[cfg(all(
target_arch = "x86_64",
target_os = "linux",
target_env = "gnu",
feature = "dhat"
))]
use jemallocator as _;
#[cfg(all( #[cfg(all(
target_arch = "x86_64", target_arch = "x86_64",
target_os = "linux", target_os = "linux",
target_env = "gnu", target_env = "gnu",
not(feature = "dhat") not(feature = "dhat")
))] ))]
#[cfg_attr( #[global_allocator]
all(target_arch = "x86_64", target_os = "linux", target_env = "gnu"),
global_allocator
)]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc; static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
#[cfg(feature = "dhat")] #[cfg(feature = "dhat")]

2
boa_engine/Cargo.toml

@ -65,7 +65,7 @@ rustc-hash = { workspace = true, features = ["std"] }
num-bigint = { workspace = true, features = ["serde"] } num-bigint = { workspace = true, features = ["serde"] }
num-integer = "0.1.45" num-integer = "0.1.45"
bitflags.workspace = true bitflags.workspace = true
indexmap.workspace = true indexmap = { workspace = true, features = ["std"] }
ryu-js = "0.2.2" ryu-js = "0.2.2"
chrono = { workspace = true, default-features = false, features = ["clock", "std"] } chrono = { workspace = true, default-features = false, features = ["clock", "std"] }
fast-float.workspace = true fast-float.workspace = true

2
boa_engine/src/vm/mod.rs

@ -32,6 +32,8 @@ mod runtime_limits;
#[cfg(feature = "flowgraph")] #[cfg(feature = "flowgraph")]
pub mod flowgraph; pub mod flowgraph;
// TODO: see if this can be exposed on all features.
#[allow(unused_imports)]
pub(crate) use opcode::{Instruction, InstructionIterator, Opcode, VaryingOperandKind}; pub(crate) use opcode::{Instruction, InstructionIterator, Opcode, VaryingOperandKind};
pub use runtime_limits::RuntimeLimits; pub use runtime_limits::RuntimeLimits;
pub use { pub use {

8
boa_engine/src/vm/opcode/mod.rs

@ -398,6 +398,8 @@ macro_rules! generate_opcodes {
impl Opcode { impl Opcode {
const MAX: usize = 2usize.pow(8) * 3; const MAX: usize = 2usize.pow(8) * 3;
// TODO: see if this can be exposed on all features.
#[allow(unused)]
const NAMES: [&'static str; Self::MAX] = [ const NAMES: [&'static str; Self::MAX] = [
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*, $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*,
$(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*, $(<generate_opcodes!(name $Variant $(=> $mapping)?)>::NAME),*,
@ -406,6 +408,8 @@ macro_rules! generate_opcodes {
/// Name of this opcode. /// Name of this opcode.
#[must_use] #[must_use]
// TODO: see if this can be exposed on all features.
#[allow(unused)]
pub(crate) const fn as_str(self) -> &'static str { pub(crate) const fn as_str(self) -> &'static str {
Self::NAMES[self as usize] Self::NAMES[self as usize]
} }
@ -505,6 +509,8 @@ macro_rules! generate_opcodes {
/// Get the [`Opcode`] of the [`Instruction`]. /// Get the [`Opcode`] of the [`Instruction`].
#[inline] #[inline]
#[must_use] #[must_use]
// TODO: see if this can be exposed on all features.
#[allow(unused)]
pub(crate) const fn opcode(&self) -> Opcode { pub(crate) const fn opcode(&self) -> Opcode {
match self { match self {
$( $(
@ -2193,6 +2199,8 @@ pub(crate) struct InstructionIterator<'bytecode> {
pc: usize, pc: usize,
} }
// TODO: see if this can be exposed on all features.
#[allow(unused)]
impl<'bytecode> InstructionIterator<'bytecode> { impl<'bytecode> InstructionIterator<'bytecode> {
/// Create a new [`InstructionIterator`] from bytecode array. /// Create a new [`InstructionIterator`] from bytecode array.
#[inline] #[inline]

1
boa_examples/Cargo.toml

@ -16,5 +16,6 @@ boa_interner.workspace = true
boa_gc.workspace = true boa_gc.workspace = true
boa_parser.workspace = true boa_parser.workspace = true
boa_runtime.workspace = true boa_runtime.workspace = true
chrono.workspace = true
smol = "1.3.0" smol = "1.3.0"
futures-util = "0.3.28" futures-util = "0.3.28"

3
boa_examples/src/bin/commuter_visitor.rs

@ -65,8 +65,7 @@ impl<'ast> VisitorMut<'ast> for CommutorVisitor {
} }
fn main() { fn main() {
let mut parser = let mut parser = Parser::new(Source::from_filepath(Path::new("./scripts/calc.js")).unwrap());
Parser::new(Source::from_filepath(Path::new("boa_examples/scripts/calc.js")).unwrap());
let mut ctx = Context::default(); let mut ctx = Context::default();
let mut script = parser.parse_script(ctx.interner_mut()).unwrap(); let mut script = parser.parse_script(ctx.interner_mut()).unwrap();

59
boa_examples/src/bin/jsdate.rs

@ -1,12 +1,30 @@
use boa_engine::{js_string, object::builtins::JsDate, Context, JsResult, JsValue}; use boa_engine::{
context::HostHooks, js_string, object::builtins::JsDate, Context, JsResult, JsValue,
};
use chrono::{DateTime, FixedOffset, LocalResult, NaiveDateTime, TimeZone};
struct CustomTimezone;
// This pins the local timezone to a system-agnostic value; in this case, UTC+3
impl HostHooks for CustomTimezone {
fn local_from_utc(&self, utc: NaiveDateTime) -> DateTime<FixedOffset> {
FixedOffset::east_opt(3 * 3600)
.unwrap()
.from_utc_datetime(&utc)
}
fn main() -> JsResult<()> { fn local_from_naive_local(&self, local: NaiveDateTime) -> LocalResult<DateTime<FixedOffset>> {
let context = &mut Context::default(); FixedOffset::east_opt(3 * 3600)
.unwrap()
.from_local_datetime(&local)
}
}
let date = JsDate::new(context); fn main() -> JsResult<()> {
let hooks: &dyn HostHooks = &CustomTimezone;
let context = &mut Context::builder().host_hooks(hooks).build().unwrap();
// 823230245000.0 let timestamp = JsDate::utc(
JsDate::utc(
&[ &[
JsValue::new(96), JsValue::new(96),
JsValue::new(1), JsValue::new(1),
@ -16,42 +34,39 @@ fn main() -> JsResult<()> {
JsValue::new(5), JsValue::new(5),
], ],
context, context,
)?; )?
// reference date: 2022-07-16T06:27:32.087241439 .as_number()
.unwrap();
assert_eq!(timestamp, 823230245000.0);
// Gets the current time in UTC time.
let date = JsDate::new(context);
// sets day of the month to 24 // sets day of the month to 24
date.set_date(24, context)?; date.set_date(24, context)?;
// 2022-07-24T06:27:11.567
// sets date to 1st of January 2000 // sets date to 1st of January 2000
date.set_full_year(&[2000.into(), 0.into(), 1.into()], context)?; date.set_full_year(&[2000.into(), 0.into(), 1.into()], context)?;
// 2000-01-01T06:26:53.984
// sets time to 10H:10M:10S:10mS // sets time to 10H:10M:10S:10mS
date.set_hours(&[23.into(), 23.into(), 23.into(), 23.into()], context)?; date.set_hours(&[23.into(), 23.into(), 23.into(), 23.into()], context)?;
// Is 2000-01-01T17:53:23.023
// Should be 2000-01-01T23:23:23.023
// sets milliseconds to 999 // sets milliseconds to 999
date.set_milliseconds(999, context)?; date.set_milliseconds(999, context)?;
// 2000-01-01T17:40:10.999
// sets time to 12M:12S:12ms // sets time to 12M:12S:12ms
date.set_minutes(&[12.into(), 12.into(), 12.into()], context)?; date.set_minutes(&[12.into(), 12.into(), 12.into()], context)?;
// Is 2000-01-01T17:42:12.012
// Should be 2000-01-01T17:12:12:012
// sets month to 9 and day to 9 // sets month to 9 (the 10th) and day to 9
date.set_month(&[9.into(), 9.into()], context)?; date.set_month(&[9.into(), 9.into()], context)?;
// 2000-10-09T04:42:12.012
// set seconds to 59 and ms to 59 // set seconds to 59 and ms to 59
date.set_seconds(&[59.into(), 59.into()], context)?; date.set_seconds(&[59.into(), 59.into()], context)?;
// 2000-10-09T04:42:59.059
assert_eq!( assert_eq!(
date.to_json(context)?, date.to_json(context)?,
JsValue::from(js_string!("2000-10-09T17:42:59.059Z")) JsValue::from(js_string!("2000-10-09T20:12:59.059Z"))
); );
assert_eq!( assert_eq!(
@ -61,17 +76,17 @@ fn main() -> JsResult<()> {
assert_eq!( assert_eq!(
date.to_iso_string(context)?, date.to_iso_string(context)?,
JsValue::from(js_string!("2000-10-09T17:42:59.059Z")) JsValue::from(js_string!("2000-10-09T20:12:59.059Z"))
); );
assert_eq!( assert_eq!(
date.to_time_string(context)?, date.to_time_string(context)?,
JsValue::from(js_string!("23:12:59 GMT+0530")) JsValue::from(js_string!("23:12:59 GMT+0300"))
); );
assert_eq!( assert_eq!(
date.to_string(context)?, date.to_string(context)?,
JsValue::from(js_string!("Mon Oct 09 2000 23:12:59 GMT+0530")) JsValue::from(js_string!("Mon Oct 09 2000 23:12:59 GMT+0300"))
); );
Ok(()) Ok(())

42
boa_examples/src/bin/loadfile.rs

@ -1,31 +1,31 @@
// This example shows how to load, parse and execute JS code from a source file // This example shows how to load, parse and execute JS code from a source file
// (./scripts/helloworld.js) // (./scripts/helloworld.js)
use std::path::Path; use std::{error::Error, path::Path};
use boa_engine::{Context, Source}; use boa_engine::{js_string, property::Attribute, Context, Source};
use boa_runtime::Console;
fn main() { /// Adds the custom runtime to the context.
fn add_runtime(context: &mut Context<'_>) {
// We first add the `console` object, to be able to call `console.log()`.
let console = Console::init(context);
context
.register_global_property(js_string!(Console::NAME), console, Attribute::all())
.expect("the console builtin shouldn't exist");
}
fn main() -> Result<(), Box<dyn Error>> {
let js_file_path = "./scripts/helloworld.js"; let js_file_path = "./scripts/helloworld.js";
match Source::from_filepath(Path::new(js_file_path)) { let source = Source::from_filepath(Path::new(js_file_path))?;
Ok(src) => {
// Instantiate the execution context // Instantiate the execution context
let mut context = Context::default(); let mut context = Context::default();
// Parse the source code // Add the runtime intrisics
match context.eval(src) { add_runtime(&mut context);
Ok(res) => { // Parse the source code and print the result
println!( println!("{}", context.eval(source)?.display());
"{}",
res.to_string(&mut context).unwrap().to_std_string_escaped() Ok(())
);
}
Err(e) => {
// Pretty print the error
eprintln!("Uncaught {e}");
}
};
}
Err(msg) => eprintln!("Error: {msg}"),
}
} }

67
boa_examples/src/bin/modulehandler.rs

@ -3,75 +3,78 @@
use boa_engine::{ use boa_engine::{
js_string, native_function::NativeFunction, prelude::JsObject, property::Attribute, Context, js_string, native_function::NativeFunction, prelude::JsObject, property::Attribute, Context,
JsResult, JsValue, Source, JsArgs, JsNativeError, JsResult, JsValue, Source,
}; };
use std::fs::read_to_string; use boa_runtime::Console;
use std::{error::Error, fs::read_to_string};
fn main() { /// Adds the custom runtime to the context.
let js_file_path = "./scripts/calctest.js"; fn add_runtime(context: &mut Context<'_>) {
let buffer = read_to_string(js_file_path); // We first add the `console` object, to be able to call `console.log()`.
let console = Console::init(context);
if buffer.is_err() { context
println!("Error: {}", buffer.unwrap_err()); .register_global_property(js_string!(Console::NAME), console, Attribute::all())
return; .expect("the console builtin shouldn't exist");
} }
fn main() -> Result<(), Box<dyn Error>> {
let js_file_path = "./scripts/calctest.js";
let buffer = read_to_string(js_file_path)?;
// Creating the execution context // Creating the execution context
let mut ctx = Context::default(); let mut ctx = Context::default();
// Adding the runtime intrinsics to the context
add_runtime(&mut ctx);
// Adding custom implementation that mimics 'require' // Adding custom implementation that mimics 'require'
ctx.register_global_callable( ctx.register_global_callable(
js_string!("require"), js_string!("require"),
0, 0,
NativeFunction::from_fn_ptr(require), NativeFunction::from_fn_ptr(require),
) )?;
.unwrap();
// Adding custom object that mimics 'module.exports' // Adding custom object that mimics 'module.exports'
let moduleobj = JsObject::default(); let moduleobj = JsObject::default();
moduleobj moduleobj.set(
.set(
js_string!("exports"), js_string!("exports"),
JsValue::from(js_string!(" ")), JsValue::from(js_string!(" ")),
false, false,
&mut ctx, &mut ctx,
) )?;
.unwrap();
ctx.register_global_property( ctx.register_global_property(
js_string!("module"), js_string!("module"),
JsValue::from(moduleobj), JsValue::from(moduleobj),
Attribute::default(), Attribute::default(),
) )?;
.unwrap();
// Instantiating the engine with the execution context // Instantiating the engine with the execution context
// Loading, parsing and executing the JS code from the source file // Loading, parsing and executing the JS code from the source file
ctx.eval(Source::from_bytes(&buffer.unwrap())).unwrap(); ctx.eval(Source::from_bytes(&buffer))?;
Ok(())
} }
// Custom implementation that mimics the 'require' module loader // Custom implementation that mimics the 'require' module loader
fn require(_: &JsValue, args: &[JsValue], ctx: &mut Context<'_>) -> JsResult<JsValue> { fn require(_: &JsValue, args: &[JsValue], ctx: &mut Context<'_>) -> JsResult<JsValue> {
let arg = args.get(0).unwrap(); let arg = args.get_or_undefined(0);
// BUG: Dev branch seems to be passing string arguments along with quotes // BUG: Dev branch seems to be passing string arguments along with quotes
let libfile = arg let libfile = arg.to_string(ctx)?.to_std_string_escaped();
.to_string(ctx)
.expect("Failed to convert to string")
.to_std_string_escaped();
// Read the module source file // Read the module source file
println!("Loading: {libfile}"); println!("Loading: {libfile}");
let buffer = read_to_string(libfile); let buffer =
if let Err(error) = buffer { read_to_string(libfile).map_err(|e| JsNativeError::typ().with_message(e.to_string()))?;
println!("Error: {error}");
Ok(JsValue::Rational(-1.0))
} else {
// Load and parse the module source // Load and parse the module source
ctx.eval(Source::from_bytes(&buffer.unwrap())).unwrap(); ctx.eval(Source::from_bytes(&buffer))?;
// Access module.exports and return as ResultValue // Access module.exports and return as ResultValue
let global_obj = ctx.global_object(); let global_obj = ctx.global_object();
let module = global_obj.get(js_string!("module"), ctx).unwrap(); let module = global_obj.get(js_string!("module"), ctx)?;
module.as_object().unwrap().get(js_string!("exports"), ctx) module
} .as_object()
.ok_or_else(|| JsNativeError::typ().with_message("`exports` property was not an object"))?
.get(js_string!("exports"), ctx)
} }

4
boa_examples/src/bin/modules.rs

@ -23,7 +23,7 @@ fn main() -> Result<(), Box<dyn Error>> {
"#; "#;
// This can be overriden with any custom implementation of `ModuleLoader`. // This can be overriden with any custom implementation of `ModuleLoader`.
let loader = &SimpleModuleLoader::new("./boa_examples/scripts/modules")?; let loader = &SimpleModuleLoader::new("./scripts/modules")?;
let dyn_loader: &dyn ModuleLoader = loader; let dyn_loader: &dyn ModuleLoader = loader;
// Just need to cast to a `ModuleLoader` before passing it to the builder. // Just need to cast to a `ModuleLoader` before passing it to the builder.
@ -39,7 +39,7 @@ fn main() -> Result<(), Box<dyn Error>> {
// Simulate as if the "fake" module is located in the modules root, just to ensure that // Simulate as if the "fake" module is located in the modules root, just to ensure that
// the loader won't double load in case someone tries to import "./main.mjs". // the loader won't double load in case someone tries to import "./main.mjs".
loader.insert( loader.insert(
Path::new("./boa_examples/scripts/modules") Path::new("./scripts/modules")
.canonicalize()? .canonicalize()?
.join("main.mjs"), .join("main.mjs"),
module.clone(), module.clone(),

8
boa_examples/src/bin/runtime_limits.rs

@ -21,11 +21,11 @@ fn main() {
// Here we exceed the limit by 1 iteration and a `RuntimeLimit` error is thrown. // Here we exceed the limit by 1 iteration and a `RuntimeLimit` error is thrown.
// //
// This error cannot be caught in JavaScript it propagates to rust caller. // This error cannot be caught in JavaScript, it can only be caught in Rust code.
let result = context.eval(Source::from_bytes( let result = context.eval(Source::from_bytes(
r" r"
try { try {
for (let i = 0; i < 11; ++i) { } for (let i = 0; i < 12; ++i) { }
} catch (e) { } catch (e) {
} }
@ -33,7 +33,7 @@ fn main() {
)); ));
assert!(result.is_err()); assert!(result.is_err());
// Preventing an infinity loops // Preventing an infinite loop
let result = context.eval(Source::from_bytes( let result = context.eval(Source::from_bytes(
r" r"
while (true) { } while (true) { }
@ -44,7 +44,7 @@ fn main() {
// The limit applies to all types of loops. // The limit applies to all types of loops.
let result = context.eval(Source::from_bytes( let result = context.eval(Source::from_bytes(
r" r"
for (let e of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) { } for (let e of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) { }
", ",
)); ));
assert!(result.is_err()); assert!(result.is_err());

3
boa_examples/src/bin/symbol_visitor.rs

@ -24,8 +24,7 @@ impl<'ast> Visitor<'ast> for SymbolVisitor {
} }
fn main() { fn main() {
let mut parser = let mut parser = Parser::new(Source::from_filepath(Path::new("./scripts/calc.js")).unwrap());
Parser::new(Source::from_filepath(Path::new("boa_examples/scripts/calc.js")).unwrap());
let mut ctx = Context::default(); let mut ctx = Context::default();
let script = parser.parse_script(ctx.interner_mut()).unwrap(); let script = parser.parse_script(ctx.interner_mut()).unwrap();

6
boa_interner/Cargo.toml

@ -11,8 +11,8 @@ repository.workspace = true
rust-version.workspace = true rust-version.workspace = true
[features] [features]
default = ["std"] serde = ["dep:serde"]
std = ["once_cell/std"] arbitrary = ["dep:arbitrary"]
[dependencies] [dependencies]
boa_macros.workspace = true boa_macros.workspace = true
@ -20,7 +20,7 @@ boa_gc.workspace = true
phf = { workspace = true, default-features = false, features = ["macros"] } phf = { workspace = true, default-features = false, features = ["macros"] }
rustc-hash = { workspace = true, default-features = false } rustc-hash = { workspace = true, default-features = false }
static_assertions.workspace = true static_assertions.workspace = true
once_cell = { workspace = true, default-features = false, features = ["critical-section"]} once_cell = { workspace = true, features = ["std"]}
indexmap.workspace = true indexmap.workspace = true
serde = { workspace = true, features = ["derive"], optional = true } serde = { workspace = true, features = ["derive"], optional = true }
arbitrary = { workspace = true, features = ["derive"], optional = true } arbitrary = { workspace = true, features = ["derive"], optional = true }

1
boa_runtime/src/console/mod.rs

@ -135,6 +135,7 @@ impl Console {
pub const NAME: &'static str = "console"; pub const NAME: &'static str = "console";
/// Initializes the `console` built-in object. /// Initializes the `console` built-in object.
#[allow(clippy::too_many_lines)]
pub fn init(context: &mut Context<'_>) -> JsObject { pub fn init(context: &mut Context<'_>) -> JsObject {
fn console_method( fn console_method(
f: fn(&JsValue, &[JsValue], &Console, &mut Context<'_>) -> JsResult<JsValue>, f: fn(&JsValue, &[JsValue], &Console, &mut Context<'_>) -> JsResult<JsValue>,

57
fuzz/Cargo.lock generated

@ -13,12 +13,6 @@ dependencies = [
"version_check", "version_check",
] ]
[[package]]
name = "allocator-api2"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5"
[[package]] [[package]]
name = "android-tzdata" name = "android-tzdata"
version = "0.1.1" version = "0.1.1"
@ -43,15 +37,6 @@ dependencies = [
"derive_arbitrary", "derive_arbitrary",
] ]
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -105,6 +90,7 @@ dependencies = [
"num-traits", "num-traits",
"num_enum", "num_enum",
"once_cell", "once_cell",
"paste",
"pollster", "pollster",
"rand", "rand",
"regress", "regress",
@ -137,7 +123,7 @@ version = "0.17.0"
dependencies = [ dependencies = [
"boa_macros", "boa_macros",
"boa_profiler", "boa_profiler",
"hashbrown 0.14.0", "hashbrown 0.14.1",
"thin-vec", "thin-vec",
] ]
@ -148,7 +134,7 @@ dependencies = [
"arbitrary", "arbitrary",
"boa_gc", "boa_gc",
"boa_macros", "boa_macros",
"hashbrown 0.14.0", "hashbrown 0.14.1",
"indexmap", "indexmap",
"once_cell", "once_cell",
"phf", "phf",
@ -227,12 +213,6 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
[[package]]
name = "critical-section"
version = "1.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216"
[[package]] [[package]]
name = "dashmap" name = "dashmap"
version = "5.5.3" version = "5.5.3"
@ -240,7 +220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"hashbrown 0.14.0", "hashbrown 0.14.1",
"lock_api", "lock_api",
"once_cell", "once_cell",
"parking_lot_core", "parking_lot_core",
@ -308,12 +288,11 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.14.0" version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" checksum = "7dfda62a12f55daeae5015f81b0baea145391cb4520f86c248fc615d72640d12"
dependencies = [ dependencies = [
"ahash", "ahash",
"allocator-api2",
] ]
[[package]] [[package]]
@ -459,12 +438,12 @@ dependencies = [
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.0.0" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897"
dependencies = [ dependencies = [
"equivalent", "equivalent",
"hashbrown 0.14.0", "hashbrown 0.14.1",
] ]
[[package]] [[package]]
@ -603,10 +582,6 @@ name = "once_cell"
version = "1.18.0" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
dependencies = [
"atomic-polyfill",
"critical-section",
]
[[package]] [[package]]
name = "parking_lot_core" name = "parking_lot_core"
@ -621,6 +596,12 @@ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]]
name = "paste"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]] [[package]]
name = "phf" name = "phf"
version = "0.11.2" version = "0.11.2"
@ -874,18 +855,18 @@ checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8"
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.48" version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.48" version = "1.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

Loading…
Cancel
Save