avm1: Implement arguments.callee

This commit is contained in:
Nathan Adams 2020-07-22 23:51:09 +02:00 committed by Mike Welsh
parent 4a56cb1062
commit f0980301da
6 changed files with 78 additions and 38 deletions

View File

@ -240,6 +240,7 @@ impl<'gc> Executable<'gc> {
base_proto: Option<Object<'gc>>,
args: &[Value<'gc>],
reason: ExecutionReason,
callee: Object<'gc>,
) -> Result<Value<'gc>, Error<'gc>> {
match self {
Executable::Native(nf) => nf(activation, ac, this, args),
@ -250,7 +251,7 @@ impl<'gc> Executable<'gc> {
);
let arguments =
ScriptObject::array(ac.gc_context, Some(activation.avm.prototypes().array));
arguments.define_value(ac.gc_context, "callee", this.into(), DontEnum.into());
arguments.define_value(ac.gc_context, "callee", callee.into(), DontEnum.into());
if !af.suppress_arguments {
for i in 0..args.len() {
@ -494,6 +495,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
) -> Result<(), Error<'gc>> {
self.base.set(name, value, activation, context)
}
fn call(
&self,
name: &str,
@ -512,6 +514,7 @@ impl<'gc> TObject<'gc> for FunctionObject<'gc> {
base_proto,
args,
ExecutionReason::FunctionCall,
(*self).into(),
)
} else {
Ok(Value::Undefined)

View File

@ -44,6 +44,7 @@ pub fn call<'gc>(
None,
args,
ExecutionReason::FunctionCall,
func,
),
_ => Ok(Value::Undefined),
}
@ -85,6 +86,7 @@ pub fn apply<'gc>(
None,
&child_args,
ExecutionReason::FunctionCall,
func,
),
_ => Ok(Value::Undefined),
}

View File

@ -59,6 +59,7 @@ impl<'gc> Watcher<'gc> {
base_proto,
&args,
ExecutionReason::Special,
self.callback,
)
} else {
Ok(Value::Undefined)
@ -292,11 +293,11 @@ impl<'gc> ScriptObject<'gc> {
if let Some(this_proto) = proto {
worked = true;
if let Some(rval) = this_proto
.call_setter(name, value.clone(), activation, context)
.and_then(|o| o.as_executable())
if let Some(rval) =
this_proto.call_setter(name, value.clone(), activation, context)
{
let _ = rval.exec(
if let Some(exec) = rval.as_executable() {
let _ = exec.exec(
"[Setter]",
activation,
context,
@ -304,10 +305,12 @@ impl<'gc> ScriptObject<'gc> {
Some(this_proto),
&[value.clone()],
ExecutionReason::Special,
rval,
);
}
}
}
}
//This signals we didn't call a virtual setter above. Normally,
//we'd resolve and return up there, but we have borrows that need
@ -357,8 +360,9 @@ impl<'gc> ScriptObject<'gc> {
}
};
if let Some(rval) = rval.and_then(|o| o.as_executable()) {
let _ = rval.exec(
if let Some(rval) = rval {
if let Some(exec) = rval.as_executable() {
let _ = exec.exec(
"[Setter]",
activation,
context,
@ -366,8 +370,10 @@ impl<'gc> ScriptObject<'gc> {
base_proto,
&[value],
ExecutionReason::Special,
rval,
);
}
}
return return_value;
}
@ -397,7 +403,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
return Ok(self.proto().map_or(Value::Undefined, Value::Object));
}
let mut exec = None;
let mut getter = None;
if let Some(value) = self
.0
@ -406,14 +412,15 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
.get(name, activation.is_case_sensitive())
{
match value {
Property::Virtual { get, .. } => exec = Some(get.to_owned()),
Property::Virtual { get, .. } => getter = Some(get.to_owned()),
Property::Stored { value, .. } => return Ok(value.to_owned()),
}
}
if let Some(get) = exec.and_then(|o| o.as_executable()) {
if let Some(getter) = getter {
if let Some(exec) = getter.as_executable() {
// Errors, even fatal ones, are completely and silently ignored here.
match get.exec(
match exec.exec(
"[Getter]",
activation,
context,
@ -421,6 +428,7 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
Some((*self).into()),
&[],
ExecutionReason::Special,
getter,
) {
Ok(value) => Ok(value),
Err(_) => Ok(Value::Undefined),
@ -428,6 +436,9 @@ impl<'gc> TObject<'gc> for ScriptObject<'gc> {
} else {
Ok(Value::Undefined)
}
} else {
Ok(Value::Undefined)
}
}
/// Set a named property on the object.

View File

@ -11,6 +11,12 @@ true
// arguments.__proto__ === Array.prototype
true
// arguments.callee
[type Function]
// arguments.callee === dump
true
// dump("a")
@ -26,6 +32,12 @@ true
// arguments.__proto__ === Array.prototype
true
// arguments.callee
[type Function]
// arguments.callee === dump
true
// arguments[0]
a
@ -44,6 +56,12 @@ true
// arguments.__proto__ === Array.prototype
true
// arguments.callee
[type Function]
// arguments.callee === dump
true
// arguments[1]
b
@ -66,6 +84,12 @@ true
// arguments.__proto__ === Array.prototype
true
// arguments.callee
[type Function]
// arguments.callee === dump
true
// arguments[3]
d