Skip to content

Commit

Permalink
Return function execution result from constructor if the function ret…
Browse files Browse the repository at this point in the history
…urned (#1463)

if the function returned
  • Loading branch information
raskad authored Aug 15, 2021
1 parent 44202ce commit 08eb767
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
11 changes: 8 additions & 3 deletions boa/src/builtins/regexp/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1211,7 +1211,10 @@ impl RegExp {
let flags = this.get_field("flags", context)?.to_string(context)?;

// 6. Let matcher be ? Construct(C, « R, flags »).
let matcher = RegExp::constructor(&c, &[this.clone(), flags.clone().into()], context)?;
let matcher = c
.as_object()
.expect("SpeciesConstructor returned non Object")
.construct(&[this.clone(), flags.clone().into()], &c, context)?;

// 7. Let lastIndex be ? ToLength(? Get(R, "lastIndex")).
let last_index = this.get_field("lastIndex", context)?.to_length(context)?;
Expand Down Expand Up @@ -1592,8 +1595,10 @@ impl RegExp {
};

// 10. Let splitter be ? Construct(C, « rx, newFlags »).
let splitter =
RegExp::constructor(&constructor, &[this.clone(), new_flags.into()], context)?;
let splitter = constructor
.as_object()
.expect("SpeciesConstructor returned non Object")
.construct(&[Value::from(rx), new_flags.into()], &constructor, context)?;

// 11. Let A be ! ArrayCreate(0).
let a = Array::array_create(0, None, context).unwrap();
Expand Down
24 changes: 21 additions & 3 deletions boa/src/object/gcobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use crate::{
function_environment_record::{BindingStatus, FunctionEnvironmentRecord},
lexical_environment::Environment,
},
exec::InterpreterState,
property::{PropertyDescriptor, PropertyKey},
symbol::WellKnownSymbols,
syntax::ast::node::RcStatementList,
Expand Down Expand Up @@ -312,6 +313,21 @@ impl GcObject {
context.pop_environment();

if construct {
// https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
// 12. If result.[[Type]] is return, then
if context.executor().get_current_state() == &InterpreterState::Return {
// a. If Type(result.[[Value]]) is Object, return NormalCompletion(result.[[Value]]).
if let Ok(v) = &result {
if v.is_object() {
return result;
}
}
}

// 13. Else, ReturnIfAbrupt(result).
result?;

// 14. Return ? constructorEnv.GetThisBinding().
this
} else {
result
Expand Down Expand Up @@ -785,12 +801,14 @@ impl GcObject {
}

// 4. If Type(C) is not Object, throw a TypeError exception.
if !c.is_object() {
let c = if let Some(c) = c.as_object() {
c
} else {
return context.throw_type_error("property 'constructor' is not an object");
}
};

// 5. Let S be ? Get(C, @@species).
let s = c.get_field(WellKnownSymbols::species(), context)?;
let s = c.get(WellKnownSymbols::species(), context)?;

// 6. If S is either undefined or null, return defaultConstructor.
if s.is_null_or_undefined() {
Expand Down

0 comments on commit 08eb767

Please sign in to comment.