Skip to content

Commit 9e8c786

Browse files
authored
feat(ecmascript): Proxy constract (#528)
1 parent 84361e4 commit 9e8c786

File tree

2 files changed

+68
-9
lines changed

2 files changed

+68
-9
lines changed

nova_vm/src/ecmascript/builtins/proxy.rs

+66-7
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ use crate::{
1111
ecmascript::{
1212
abstract_operations::{
1313
operations_on_objects::{
14-
call, call_function, create_array_from_list, get_object_method,
14+
call, call_function, construct, create_array_from_list, get_object_method,
1515
try_get_object_method,
1616
},
17-
testing_and_comparison::{is_extensible, same_value},
17+
testing_and_comparison::{is_constructor, is_extensible, same_value},
1818
type_conversion::to_boolean,
1919
},
2020
builtins::ArgumentsList,
@@ -1322,12 +1322,71 @@ impl InternalMethods for Proxy<'_> {
13221322

13231323
fn internal_construct(
13241324
self,
1325-
_agent: &mut Agent,
1326-
_arguments_list: ArgumentsList,
1327-
_new_target: Function,
1328-
_gc: GcScope,
1325+
agent: &mut Agent,
1326+
arguments_list: ArgumentsList,
1327+
new_target: Function,
1328+
mut gc: GcScope<'_, '_>,
13291329
) -> JsResult<Object> {
1330-
todo!()
1330+
// 1. Perform ? ValidateNonRevokedProxy(O).
1331+
// 2. Let target be O.[[ProxyTarget]].
1332+
// 4. Let handler be O.[[ProxyHandler]].
1333+
// 5. Assert: handler is an Object.
1334+
let NonRevokedProxy {
1335+
target,
1336+
mut handler,
1337+
} = validate_non_revoked_proxy(agent, self, gc.nogc())?;
1338+
// 3. Assert: IsConstructor(target) is true.
1339+
let target = is_constructor(agent, target).unwrap();
1340+
// 6. Let trap be ? GetMethod(handler, "construct").
1341+
let trap = if let TryResult::Continue(trap) = try_get_object_method(
1342+
agent,
1343+
handler,
1344+
BUILTIN_STRING_MEMORY.construct.into(),
1345+
gc.nogc(),
1346+
) {
1347+
trap?
1348+
} else {
1349+
let scoped_handler = handler.scope(agent, gc.nogc());
1350+
let trap = get_object_method(
1351+
agent,
1352+
handler,
1353+
BUILTIN_STRING_MEMORY.construct.into(),
1354+
gc.reborrow(),
1355+
)?
1356+
.map(Function::unbind);
1357+
let gc = gc.nogc();
1358+
let trap = trap.map(|f| f.bind(gc));
1359+
handler = scoped_handler.get(agent).bind(gc);
1360+
trap
1361+
};
1362+
// 7. If trap is undefined, then
1363+
let Some(trap) = trap else {
1364+
// a. Return ? Construct(target, argumentsList, newTarget).
1365+
return construct(agent, target, Some(arguments_list), Some(new_target), gc);
1366+
};
1367+
// 8. Let argArray be CreateArrayFromList(argumentsList).
1368+
let arg_array = create_array_from_list(agent, arguments_list.0, gc.nogc());
1369+
// 9. Let newObj be ? Call(trap, handler, « target, argArray, newTarget »).
1370+
let new_obj = call_function(
1371+
agent,
1372+
trap.unbind(),
1373+
handler.into_value(),
1374+
Some(ArgumentsList(&[
1375+
target.into_value(),
1376+
arg_array.into_value(),
1377+
new_target.into_value(),
1378+
])),
1379+
gc.reborrow(),
1380+
)?;
1381+
// 11. Return newObj.
1382+
new_obj
1383+
.try_into()
1384+
// 10. If newObj is not an Object, throw a TypeError exception.
1385+
.or(Err(agent.throw_exception_with_static_message(
1386+
ExceptionType::TypeError,
1387+
"proxy [[Construct]] must return an object",
1388+
gc.nogc(),
1389+
)))
13311390
}
13321391
}
13331392

tests/metrics.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"results": {
3-
"crash": 14288,
4-
"fail": 7295,
3+
"crash": 14290,
4+
"fail": 7293,
55
"pass": 23659,
66
"skip": 46,
77
"timeout": 3,

0 commit comments

Comments
 (0)