Skip to content

Commit

Permalink
Added the required glue to interpret async tests in the boa tester
Browse files Browse the repository at this point in the history
  • Loading branch information
Razican committed Jun 9, 2022
1 parent 681e6f6 commit f13fd08
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 10 deletions.
2 changes: 1 addition & 1 deletion boa_engine/src/builtins/promise/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -682,7 +682,7 @@ impl Promise {
// c. If promise.[[PromiseIsHandled]] is false, perform HostPromiseRejectionTracker(promise, "handle").
if !self.promise_is_handled {
// HostPromiseRejectionTracker(promise, "handle")
todo!(); // TODO
// TODO
}

// d. Let rejectJob be NewPromiseReactionJob(rejectReaction, reason).
Expand Down
63 changes: 54 additions & 9 deletions boa_tester/src/exec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ use super::{
Harness, Outcome, Phase, SuiteResult, Test, TestFlags, TestOutcomeResult, TestResult,
TestSuite, IGNORED,
};
use boa_engine::{syntax::Parser, Context, JsResult, JsValue};
use boa_engine::{
builtins::JsArgs, object::FunctionBuilder, property::Attribute, syntax::Parser, Context,
JsResult, JsValue,
};
use boa_gc::{Cell, Finalize, Gc, Trace};
use colored::Colorize;
use rayon::prelude::*;
use std::panic;
Expand Down Expand Up @@ -165,14 +169,16 @@ impl Test {
)) {
let res = panic::catch_unwind(|| match self.expected_outcome {
Outcome::Positive => {
// TODO: implement async and add `harness/doneprintHandle.js` to the includes.
let mut context = Context::default();

match self.set_up_env(harness, &mut context) {
let callback_obj = CallbackObject::default();
// TODO: timeout
match self.set_up_env(harness, &mut context, callback_obj.clone()) {
Ok(_) => {
let res = context.eval(&test_content);

let passed = res.is_ok();
let passed = res.is_ok()
&& matches!(*callback_obj.result.borrow(), Some(true) | None);
let text = match res {
Ok(val) => val.display().to_string(),
Err(e) => format!("Uncaught {}", e.display()),
Expand Down Expand Up @@ -215,7 +221,8 @@ impl Test {
if let Err(e) = Parser::new(test_content.as_bytes()).parse_all(&mut context) {
(false, format!("Uncaught {e}"))
} else {
match self.set_up_env(harness, &mut context) {
// TODO: timeout
match self.set_up_env(harness, &mut context, CallbackObject::default()) {
Ok(_) => match context.eval(&test_content) {
Ok(res) => (false, res.display().to_string()),
Err(e) => {
Expand Down Expand Up @@ -306,9 +313,14 @@ impl Test {
}

/// Sets the environment up to run the test.
fn set_up_env(&self, harness: &Harness, context: &mut Context) -> Result<(), String> {
fn set_up_env(
&self,
harness: &Harness,
context: &mut Context,
callback_obj: CallbackObject,
) -> Result<(), String> {
// Register the print() function.
context.register_global_function("print", 1, test262_print);
Self::register_print_fn(context, callback_obj);

// add the $262 object.
let _js262 = js262::init(context);
Expand Down Expand Up @@ -349,9 +361,42 @@ impl Test {

Ok(())
}

/// Registers the print function in the context.
fn register_print_fn(context: &mut Context, callback_object: CallbackObject) {
// We use `FunctionBuilder` to define a closure with additional captures.
let js_function =
FunctionBuilder::closure_with_captures(context, test262_print, callback_object)
.name("print")
.length(1)
.build();

context.register_global_property(
"print",
js_function,
Attribute::WRITABLE | Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
);
}
}

/// Object which includes the result of the async operation.
#[derive(Debug, Clone, Default, Trace, Finalize)]
struct CallbackObject {
result: Gc<Cell<Option<bool>>>,
}

/// `print()` function required by the test262 suite.
fn test262_print(_this: &JsValue, _: &[JsValue], _context: &mut Context) -> JsResult<JsValue> {
todo!("print() function");
#[allow(clippy::unnecessary_wraps)]
fn test262_print(
_this: &JsValue,
args: &[JsValue],
captures: &mut CallbackObject,
_context: &mut Context,
) -> JsResult<JsValue> {
if let Some(message) = args.get_or_undefined(0).as_string() {
*captures.result.borrow_mut() = Some(message.as_str() == "Test262:AsyncTestComplete");
} else {
*captures.result.borrow_mut() = Some(false);
}
Ok(JsValue::undefined())
}

0 comments on commit f13fd08

Please sign in to comment.