Skip to content

Commit

Permalink
Merge c836ec9 into dc82aa2
Browse files Browse the repository at this point in the history
  • Loading branch information
HalidOdat authored Oct 5, 2020
2 parents dc82aa2 + c836ec9 commit f30c6e4
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 2 deletions.
16 changes: 14 additions & 2 deletions boa/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use crate::{
builtins::{Array, BuiltIn},
environment::lexical_environment::Environment,
object::{ConstructorBuilder, Object, ObjectData, PROTOTYPE},
object::{ConstructorBuilder, FunctionBuilder, Object, ObjectData, PROTOTYPE},
property::{Attribute, Property},
syntax::ast::node::{FormalParameter, RcStatementList},
BoaProfiler, Context, Result, Value,
Expand Down Expand Up @@ -301,13 +301,17 @@ pub struct BuiltInFunctionObject;
impl BuiltInFunctionObject {
pub const LENGTH: usize = 1;

fn constructor(this: &Value, _args: &[Value], _context: &mut Context) -> Result<Value> {
fn constructor(this: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
this.set_data(ObjectData::Function(Function::BuiltIn(
BuiltInFunction(|_, _, _| Ok(Value::undefined())),
FunctionFlags::CALLABLE | FunctionFlags::CONSTRUCTABLE,
)));
Ok(this.clone())
}

fn prototype(_: &Value, _: &[Value], _: &mut Context) -> Result<Value> {
Ok(Value::undefined())
}
}

impl BuiltIn for BuiltInFunctionObject {
Expand All @@ -320,6 +324,14 @@ impl BuiltIn for BuiltInFunctionObject {
fn init(context: &mut Context) -> (&'static str, Value, Attribute) {
let _timer = BoaProfiler::global().start_event("function", "init");

let function_prototype = context.standard_objects().function_object().prototype();
FunctionBuilder::new(context, Self::prototype)
.name("")
.length(0)
.callable(true)
.constructable(false)
.build_function_prototype(&function_prototype);

let function_object = ConstructorBuilder::with_standard_object(
context,
Self::constructor,
Expand Down
53 changes: 53 additions & 0 deletions boa/src/builtins/function/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,56 @@ fn self_mutating_function_when_constructing() {
3
);
}

#[test]
fn call_function_prototype() {
let mut engine = Context::new();
let func = r#"
Function.prototype()
"#;
let value = forward_val(&mut engine, func).unwrap();
assert!(value.is_undefined());
}

#[test]
fn call_function_prototype_with_arguments() {
let mut engine = Context::new();
let func = r#"
Function.prototype(1, "", new String(""))
"#;
let value = forward_val(&mut engine, func).unwrap();
assert!(value.is_undefined());
}

#[test]
fn call_function_prototype_with_new() {
let mut engine = Context::new();
let func = r#"
new Function.prototype()
"#;
let value = forward_val(&mut engine, func);
assert!(value.is_err());
}

#[test]
fn function_prototype_name() {
let mut engine = Context::new();
let func = r#"
Function.prototype.name
"#;
let value = forward_val(&mut engine, func).unwrap();
assert!(value.is_string());
assert!(value.as_string().unwrap().is_empty());
}

#[test]
#[allow(clippy::float_cmp)]
fn function_prototype_length() {
let mut engine = Context::new();
let func = r#"
Function.prototype.length
"#;
let value = forward_val(&mut engine, func).unwrap();
assert!(value.is_number());
assert_eq!(value.as_number().unwrap(), 0.0);
}
23 changes: 23 additions & 0 deletions boa/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,29 @@ impl<'context> FunctionBuilder<'context> {

GcObject::new(function)
}

/// Initializes the `Function.prototype` function object.
pub(crate) fn build_function_prototype(&mut self, object: &GcObject) {
let mut object = object.borrow_mut();
object.data = ObjectData::Function(Function::BuiltIn(
self.function,
FunctionFlags::from_parameters(self.callable, self.constructable),
));
object.set_prototype_instance(
self.context
.standard_objects()
.object_object()
.prototype()
.into(),
);
let attribute = Attribute::READONLY | Attribute::NON_ENUMERABLE | Attribute::PERMANENT;
if let Some(name) = self.name.take() {
object.insert_property("name", name, attribute);
} else {
object.insert_property("name", "", attribute);
}
object.insert_property("length", self.length, attribute);
}
}

/// Builder for creating objects with properties.
Expand Down

0 comments on commit f30c6e4

Please sign in to comment.