Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into set-timeout
Browse files Browse the repository at this point in the history
  • Loading branch information
hansl committed Jan 14, 2025
2 parents 9ebb876 + f64d937 commit 9e931a2
Show file tree
Hide file tree
Showing 27 changed files with 783 additions and 439 deletions.
8 changes: 8 additions & 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ arbitrary = "1"
bitflags = "2.5.0"
clap = "4.5.23"
colored = "2.2.0"
cow-utils = "0.1.3"
fast-float2 = "0.2.3"
hashbrown = "0.15.2"
indexmap = { version = "2.7.0", default-features = false }
Expand Down
62 changes: 40 additions & 22 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ mod helper;
use boa_engine::{
builtins::promise::PromiseState,
context::ContextBuilder,
job::{FutureJob, JobQueue, NativeJob},
job::{Job, JobExecutor, NativeAsyncJob, PromiseJob},
module::{Module, SimpleModuleLoader},
optimizer::OptimizerOptions,
script::Script,
vm::flowgraph::{Direction, Graph},
Context, JsError, Source,
Context, JsError, JsResult, Source,
};
use boa_parser::source::ReadChar;
use clap::{Parser, ValueEnum, ValueHint};
Expand Down Expand Up @@ -292,7 +292,7 @@ fn evaluate_file(
);

let promise = module.load_link_evaluate(context);
context.run_jobs();
context.run_jobs().map_err(|err| err.into_erased(context))?;
let result = promise.state();

return match result {
Expand All @@ -308,9 +308,9 @@ fn evaluate_file(
Ok(v) => println!("{}", v.display()),
Err(v) => eprintln!("Uncaught {v}"),
}
context.run_jobs();

Ok(())
context
.run_jobs()
.map_err(|err| err.into_erased(context).into())
}

fn evaluate_files(args: &Opt, context: &mut Context, loader: &SimpleModuleLoader) {
Expand All @@ -336,10 +336,10 @@ fn main() -> Result<()> {

let args = Opt::parse();

let queue = Rc::new(Jobs::default());
let executor = Rc::new(Executor::default());
let loader = Rc::new(SimpleModuleLoader::new(&args.root).map_err(|e| eyre!(e.to_string()))?);
let mut context = ContextBuilder::new()
.job_queue(queue)
.job_executor(executor)
.module_loader(loader.clone())
.build()
.map_err(|e| eyre!(e.to_string()))?;
Expand Down Expand Up @@ -425,7 +425,9 @@ fn main() -> Result<()> {
eprintln!("{}: {}", "Uncaught".red(), v.to_string().red());
}
}
context.run_jobs();
if let Err(err) = context.run_jobs() {
eprintln!("{err}");
};
}
}

Expand Down Expand Up @@ -453,29 +455,45 @@ fn add_runtime(context: &mut Context) {
}

#[derive(Default)]
struct Jobs(RefCell<VecDeque<NativeJob>>);
struct Executor {
promise_jobs: RefCell<VecDeque<PromiseJob>>,
async_jobs: RefCell<VecDeque<NativeAsyncJob>>,
}

impl JobQueue for Jobs {
fn enqueue_promise_job(&self, job: NativeJob, _: &mut Context) {
self.0.borrow_mut().push_back(job);
impl JobExecutor for Executor {
fn enqueue_job(&self, job: Job, _: &mut Context) {
match job {
Job::PromiseJob(job) => self.promise_jobs.borrow_mut().push_back(job),
Job::AsyncJob(job) => self.async_jobs.borrow_mut().push_back(job),
job => eprintln!("unsupported job type {job:?}"),
}
}

fn run_jobs(&self, context: &mut Context) {
fn run_jobs(&self, context: &mut Context) -> JsResult<()> {
loop {
let jobs = std::mem::take(&mut *self.0.borrow_mut());
if jobs.is_empty() {
return;
if self.promise_jobs.borrow().is_empty() && self.async_jobs.borrow().is_empty() {
return Ok(());
}

let jobs = std::mem::take(&mut *self.promise_jobs.borrow_mut());
for job in jobs {
if let Err(e) = job.call(context) {
eprintln!("Uncaught {e}");
}
}
}
}

fn enqueue_future_job(&self, future: FutureJob, _: &mut Context) {
let job = pollster::block_on(future);
self.0.borrow_mut().push_back(job);
let async_jobs = std::mem::take(&mut *self.async_jobs.borrow_mut());
for async_job in async_jobs {
if let Err(err) = pollster::block_on(async_job.call(&RefCell::new(context))) {
eprintln!("Uncaught {err}");
}
let jobs = std::mem::take(&mut *self.promise_jobs.borrow_mut());
for job in jobs {
if let Err(e) = job.call(context) {
eprintln!("Uncaught {e}");
}
}
}
}
}
}
3 changes: 3 additions & 0 deletions clippy.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
doc-valid-idents = ['ECMAScript', 'JavaScript', 'SpiderMonkey', 'GitHub']
allow-print-in-tests = true
disallowed-methods = [
{ path = "str::to_ascii_uppercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_ascii_uppercase` instead." },
]
1 change: 1 addition & 0 deletions core/engine/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ boa_macros.workspace = true
boa_ast.workspace = true
boa_parser.workspace = true
boa_string.workspace = true
cow-utils.workspace = true
serde = { workspace = true, features = ["derive", "rc"] }
serde_json.workspace = true
rand.workspace = true
Expand Down
22 changes: 12 additions & 10 deletions core/engine/src/builtins/promise/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
builtins::{Array, BuiltInObject},
context::intrinsics::{Intrinsics, StandardConstructor, StandardConstructors},
error::JsNativeError,
job::{JobCallback, NativeJob},
job::{JobCallback, PromiseJob},
js_string,
native_function::NativeFunction,
object::{
Expand Down Expand Up @@ -1888,8 +1888,8 @@ impl Promise {

// c. Perform HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]]).
context
.job_queue()
.enqueue_promise_job(fulfill_job, context);
.job_executor()
.enqueue_job(fulfill_job.into(), context);
}

// 11. Else,
Expand All @@ -1909,7 +1909,9 @@ impl Promise {
let reject_job = new_promise_reaction_job(reject_reaction, reason.clone(), context);

// e. Perform HostEnqueuePromiseJob(rejectJob.[[Job]], rejectJob.[[Realm]]).
context.job_queue().enqueue_promise_job(reject_job, context);
context
.job_executor()
.enqueue_job(reject_job.into(), context);

// 12. Set promise.[[PromiseIsHandled]] to true.
promise
Expand Down Expand Up @@ -1985,7 +1987,7 @@ impl Promise {
let job = new_promise_reaction_job(reaction, argument.clone(), context);

// b. Perform HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]).
context.job_queue().enqueue_promise_job(job, context);
context.job_executor().enqueue_job(job.into(), context);
}
// 2. Return unused.
}
Expand Down Expand Up @@ -2178,7 +2180,7 @@ impl Promise {
);

// 15. Perform HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]).
context.job_queue().enqueue_promise_job(job, context);
context.job_executor().enqueue_job(job.into(), context);

// 16. Return undefined.
Ok(JsValue::undefined())
Expand Down Expand Up @@ -2239,7 +2241,7 @@ fn new_promise_reaction_job(
mut reaction: ReactionRecord,
argument: JsValue,
context: &mut Context,
) -> NativeJob {
) -> PromiseJob {
// Inverting order since `job` captures `reaction` by value.

// 2. Let handlerRealm be null.
Expand Down Expand Up @@ -2320,7 +2322,7 @@ fn new_promise_reaction_job(
};

// 4. Return the Record { [[Job]]: job, [[Realm]]: handlerRealm }.
NativeJob::with_realm(job, realm, context)
PromiseJob::with_realm(job, realm, context)
}

/// More information:
Expand All @@ -2332,7 +2334,7 @@ fn new_promise_resolve_thenable_job(
thenable: JsValue,
then: JobCallback,
context: &mut Context,
) -> NativeJob {
) -> PromiseJob {
// Inverting order since `job` captures variables by value.

// 2. Let getThenRealmResult be Completion(GetFunctionRealm(then.[[Callback]])).
Expand Down Expand Up @@ -2374,5 +2376,5 @@ fn new_promise_resolve_thenable_job(
};

// 6. Return the Record { [[Job]]: job, [[Realm]]: thenRealm }.
NativeJob::with_realm(job, realm, context)
PromiseJob::with_realm(job, realm, context)
}
3 changes: 1 addition & 2 deletions core/engine/src/builtins/promise/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ fn promise() {
count += 1;
"#}),
TestAction::assert_eq("count", 2),
#[allow(clippy::redundant_closure_for_method_calls)]
TestAction::inspect_context(|ctx| ctx.run_jobs()),
TestAction::inspect_context(|ctx| ctx.run_jobs().unwrap()),
TestAction::assert_eq("count", 3),
]);
}
4 changes: 2 additions & 2 deletions core/engine/src/builtins/temporal/time_zone/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#![allow(dead_code)]

use crate::{builtins::temporal::to_zero_padded_decimal_string, Context};

use cow_utils::CowUtils;
// -- TimeZone Abstract Operations --

/// Abstract operation `DefaultTimeZone ( )`
Expand Down Expand Up @@ -96,7 +96,7 @@ fn canonicalize_time_zone_name(time_zone: &str) -> String {
// do not include local political rules for any time zones performs the following steps when
// called:
// 1. Assert: timeZone is an ASCII-case-insensitive match for "UTC".
assert_eq!(time_zone.to_ascii_uppercase(), "UTC");
assert_eq!(time_zone.cow_to_ascii_uppercase(), "UTC");
// 2. Return "UTC".
"UTC".to_owned()
}
Loading

0 comments on commit 9e931a2

Please sign in to comment.