Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Implement ProxyBuilder #2076

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions boa_engine/src/builtins/function/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ mod tests;
///
/// Native functions need to have this signature in order to
/// be callable from Javascript.
///
/// # Arguments
///
/// - The first argument represents the `this` variable of every Javascript function.
///
/// - The second argument represents a list of all arguments passed to the function.
///
/// - The last argument is the [`Context`] of the engine.
pub type NativeFunctionSignature = fn(&JsValue, &[JsValue], &mut Context) -> JsResult<JsValue>;

// Allows restricting closures to only `Copy` ones.
Expand Down
74 changes: 37 additions & 37 deletions boa_engine/src/builtins/proxy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,12 @@

use crate::{
builtins::{BuiltIn, JsArgs},
object::{ConstructorBuilder, FunctionBuilder, JsObject, ObjectData},
object::{ConstructorBuilder, FunctionBuilder, JsFunction, JsObject, ObjectData},
Context, JsResult, JsValue,
};
use boa_gc::{Finalize, Trace};
use boa_profiler::Profiler;
use tap::{Conv, Pipe};

/// Javascript `Proxy` object.
#[derive(Debug, Clone, Trace, Finalize)]
pub struct Proxy {
Expand Down Expand Up @@ -50,7 +49,7 @@ impl BuiltIn for Proxy {
impl Proxy {
const LENGTH: usize = 2;

fn new(target: JsObject, handler: JsObject) -> Self {
pub(crate) fn new(target: JsObject, handler: JsObject) -> Self {
Self {
data: Some((target, handler)),
}
Expand Down Expand Up @@ -82,7 +81,7 @@ impl Proxy {
}

// 2. Return ? ProxyCreate(target, handler).
Self::create(args.get_or_undefined(0), args.get_or_undefined(1), context)
Self::create(args.get_or_undefined(0), args.get_or_undefined(1), context).map(JsValue::from)
}

// `10.5.14 ProxyCreate ( target, handler )`
Expand All @@ -91,7 +90,11 @@ impl Proxy {
// - [ECMAScript reference][spec]
//
// [spec]: https://tc39.es/ecma262/#sec-proxycreate
fn create(target: &JsValue, handler: &JsValue, context: &mut Context) -> JsResult<JsValue> {
pub(crate) fn create(
target: &JsValue,
handler: &JsValue,
context: &mut Context,
) -> JsResult<JsObject> {
// 1. If Type(target) is not Object, throw a TypeError exception.
let target = target.as_object().ok_or_else(|| {
context.construct_type_error("Proxy constructor called with non-object target")
Expand Down Expand Up @@ -120,52 +123,49 @@ impl Proxy {
);

// 8. Return P.
Ok(p.into())
Ok(p)
}

/// `28.2.2.1 Proxy.revocable ( target, handler )`
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-proxy.revocable
fn revocable(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Let p be ? ProxyCreate(target, handler).
let p = Self::create(args.get_or_undefined(0), args.get_or_undefined(1), context)?;

pub(crate) fn revoker(proxy: JsObject, context: &mut Context) -> JsFunction {
// 3. Let revoker be ! CreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »).
// 4. Set revoker.[[RevocableProxy]] to p.
let revoker = FunctionBuilder::closure_with_captures(
FunctionBuilder::closure_with_captures(
context,
|_, _, revocable_proxy, _| {
// a. Let F be the active function object.
// b. Let p be F.[[RevocableProxy]].
// c. If p is null, return undefined.
if revocable_proxy.is_null() {
return Ok(JsValue::undefined());
}

let p = revocable_proxy
.as_object()
.expect("[[RevocableProxy]] must be an object or null");

// e. Assert: p is a Proxy object.
// f. Set p.[[ProxyTarget]] to null.
// g. Set p.[[ProxyHandler]] to null.
p.borrow_mut()
.as_proxy_mut()
.expect("[[RevocableProxy]] must be a proxy object")
.data = None;

// d. Set F.[[RevocableProxy]] to null.
*revocable_proxy = JsValue::Null;
if let Some(p) = revocable_proxy.take() {
// e. Assert: p is a Proxy object.
// f. Set p.[[ProxyTarget]] to null.
// g. Set p.[[ProxyHandler]] to null.
p.borrow_mut()
.as_proxy_mut()
.expect("[[RevocableProxy]] must be a proxy object")
.data = None;
}

// c. If p is null, return undefined.
// h. Return undefined.
Ok(JsValue::undefined())
},
p.clone(),
Some(proxy),
)
.build();
.build()
}

/// `28.2.2.1 Proxy.revocable ( target, handler )`
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-proxy.revocable
fn revocable(_: &JsValue, args: &[JsValue], context: &mut Context) -> JsResult<JsValue> {
// 1. Let p be ? ProxyCreate(target, handler).
let p = Self::create(args.get_or_undefined(0), args.get_or_undefined(1), context)?;

// Revoker creation steps on `Proxy::revoker`
let revoker = Self::revoker(p.clone(), context);

// 5. Let result be ! OrdinaryObjectCreate(%Object.prototype%).
let result = context.construct_object();
Expand Down
1 change: 0 additions & 1 deletion boa_engine/src/object/internal_methods/bound_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use super::{InternalObjectMethods, ORDINARY_INTERNAL_METHODS};
pub(crate) static BOUND_FUNCTION_EXOTIC_INTERNAL_METHODS: InternalObjectMethods =
InternalObjectMethods {
__call__: Some(bound_function_exotic_call),
__construct__: None,
..ORDINARY_INTERNAL_METHODS
};

Expand Down
25 changes: 2 additions & 23 deletions boa_engine/src/object/internal_methods/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,36 +32,15 @@ pub(crate) static PROXY_EXOTIC_INTERNAL_METHODS_BASIC: InternalObjectMethods =

pub(crate) static PROXY_EXOTIC_INTERNAL_METHODS_WITH_CALL: InternalObjectMethods =
InternalObjectMethods {
__get_prototype_of__: proxy_exotic_get_prototype_of,
__set_prototype_of__: proxy_exotic_set_prototype_of,
__is_extensible__: proxy_exotic_is_extensible,
__prevent_extensions__: proxy_exotic_prevent_extensions,
__get_own_property__: proxy_exotic_get_own_property,
__define_own_property__: proxy_exotic_define_own_property,
__has_property__: proxy_exotic_has_property,
__get__: proxy_exotic_get,
__set__: proxy_exotic_set,
__delete__: proxy_exotic_delete,
__own_property_keys__: proxy_exotic_own_property_keys,
__call__: Some(proxy_exotic_call),
__construct__: None,
..PROXY_EXOTIC_INTERNAL_METHODS_BASIC
};

pub(crate) static PROXY_EXOTIC_INTERNAL_METHODS_ALL: InternalObjectMethods =
InternalObjectMethods {
__get_prototype_of__: proxy_exotic_get_prototype_of,
__set_prototype_of__: proxy_exotic_set_prototype_of,
__is_extensible__: proxy_exotic_is_extensible,
__prevent_extensions__: proxy_exotic_prevent_extensions,
__get_own_property__: proxy_exotic_get_own_property,
__define_own_property__: proxy_exotic_define_own_property,
__has_property__: proxy_exotic_has_property,
__get__: proxy_exotic_get,
__set__: proxy_exotic_set,
__delete__: proxy_exotic_delete,
__own_property_keys__: proxy_exotic_own_property_keys,
__call__: Some(proxy_exotic_call),
__construct__: Some(proxy_exotic_construct),
..PROXY_EXOTIC_INTERNAL_METHODS_BASIC
};

/// `10.5.1 [[GetPrototypeOf]] ( )`
Expand Down