Skip to content

Commit 3dfdf5a

Browse files
committed
avm1: Add TDisplayObject::object1_or_bare convenience method
1 parent f19e216 commit 3dfdf5a

File tree

8 files changed

+41
-47
lines changed

8 files changed

+41
-47
lines changed

core/src/avm1/activation.rs

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -343,11 +343,10 @@ impl<'a, 'gc> Activation<'a, 'gc> {
343343
active_clip: DisplayObject<'gc>,
344344
code: SwfSlice,
345345
) -> Result<ReturnType<'gc>, Error<'gc>> {
346-
let mut parent_activation =
346+
// TODO(moulins): remove this activation, it's useless.
347+
let parent_activation =
347348
Activation::from_nothing(self.context, self.id.child("[Actions Parent]"), active_clip);
348-
let clip_obj = active_clip
349-
.object1_or_undef()
350-
.coerce_to_object(&mut parent_activation);
349+
let clip_obj = active_clip.object1_or_bare(parent_activation.gc());
351350
let child_scope = Gc::new(
352351
parent_activation.gc(),
353352
Scope::new(
@@ -866,7 +865,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
866865
let swf_version = self.swf_version();
867866
let func_data = parent_data.to_unbounded_subslice(action.actions);
868867
let constant_pool = self.constant_pool();
869-
let bc = self.base_clip.object1_or_undef().coerce_to_object(self);
868+
let bc = self.base_clip.object1_or_bare(self.gc());
870869
let func = Avm1Function::from_swf_function(
871870
self.gc(),
872871
swf_version,
@@ -1253,7 +1252,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
12531252
}
12541253
if is_load_vars {
12551254
if let Some(clip_target) = clip_target {
1256-
let target_obj = clip_target.object1_or_undef().coerce_to_object(self);
1255+
let target_obj = clip_target.object1_or_bare(self.gc());
12571256
let request = self.locals_into_request(
12581257
url,
12591258
NavigationMethod::from_send_vars_method(action.send_vars_method()),
@@ -1792,10 +1791,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
17921791
// Revert the target to the base clip, or `None` if the base was also removed
17931792
self.set_target_clip(Some(self.base_clip()));
17941793

1795-
let clip_obj = self
1796-
.target_clip_or_root()
1797-
.object1_or_undef()
1798-
.coerce_to_object(self);
1794+
let clip_obj = self.target_clip_or_root().object1_or_bare(self.gc());
17991795

18001796
self.set_scope(Scope::new_target_scope(self.scope(), clip_obj, self.gc()));
18011797
}
@@ -1940,10 +1936,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
19401936
}
19411937
};
19421938

1943-
let clip_obj = self
1944-
.target_clip_or_base_clip()
1945-
.object1_or_undef()
1946-
.coerce_to_object(self);
1939+
let clip_obj = self.target_clip_or_base_clip().object1_or_bare(self.gc());
19471940

19481941
self.set_scope(Scope::new_target_scope(self.scope(), clip_obj, self.gc()));
19491942
Ok(FrameControl::Continue)
@@ -2503,7 +2496,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
25032496
}
25042497

25052498
let root = start.avm1_root();
2506-
let start = start.object1_or_undef().coerce_to_object(self);
2499+
let start = start.object1_or_bare(self.gc());
25072500
Ok(self
25082501
.resolve_target_path(root, start, &path, false, true)?
25092502
.and_then(|o| o.as_display_object()))
@@ -2535,7 +2528,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
25352528
// (`/bar` means `_root.bar`)
25362529
let (mut object, mut is_slash_path) = if path.starts_with(b'/') {
25372530
path = &path[1..];
2538-
(root.object1_or_undef().coerce_to_object(self), true)
2531+
(root.object1_or_bare(self.gc()), true)
25392532
} else {
25402533
(start, false)
25412534
};
@@ -2589,7 +2582,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
25892582
if first_element && name == b"this" {
25902583
self.this_cell()
25912584
} else if first_element && name == b"_root" {
2592-
self.root_object()
2585+
self.base_clip().avm1_root().object1_or_undef()
25932586
} else {
25942587
// Get the value from the object.
25952588
// Resolves display object instances first, then local variables.
@@ -2869,11 +2862,6 @@ impl<'a, 'gc> Activation<'a, 'gc> {
28692862
self.target_clip().unwrap_or_else(|| self.base_clip())
28702863
}
28712864

2872-
/// Obtain the value of `_root`.
2873-
pub fn root_object(&self) -> Value<'gc> {
2874-
self.base_clip().avm1_root().object1_or_undef()
2875-
}
2876-
28772865
/// Returns whether property keys should be case sensitive based on the current SWF version.
28782866
pub fn is_case_sensitive(&self) -> bool {
28792867
crate::avm1::runtime::Avm1::is_case_sensitive(self.swf_version())
@@ -2926,7 +2914,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
29262914
Scope::new(
29272915
self.scope,
29282916
ScopeClass::Target,
2929-
object.object1_or_undef().coerce_to_object(self),
2917+
object.object1_or_bare(self.gc()),
29302918
),
29312919
);
29322920
}
@@ -3022,7 +3010,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
30223010
let base_clip = self.base_clip();
30233011
let new_target_clip;
30243012
let root = base_clip.avm1_root();
3025-
let start = base_clip.object1_or_undef().coerce_to_object(self);
3013+
let start = base_clip.object1_or_bare(self.gc());
30263014
if target.is_empty() {
30273015
new_target_clip = Some(base_clip);
30283016
} else if let Some(clip) = self
@@ -3058,10 +3046,7 @@ impl<'a, 'gc> Activation<'a, 'gc> {
30583046

30593047
self.set_target_clip(new_target_clip);
30603048

3061-
let clip_obj = self
3062-
.target_clip_or_root()
3063-
.object1_or_undef()
3064-
.coerce_to_object(self);
3049+
let clip_obj = self.target_clip_or_root().object1_or_bare(self.gc());
30653050

30663051
self.set_scope(Scope::new_target_scope(self.scope(), clip_obj, self.gc()));
30673052
Ok(FrameControl::Continue)

core/src/avm1/debug.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,12 @@ impl<'a> VariableDumper<'a> {
147147
Value::Object(object) => {
148148
self.print_object(object, activation);
149149
}
150-
Value::MovieClip(_) => {
151-
let obj = value.coerce_to_object(activation);
152-
self.print_object(obj, activation);
150+
Value::MovieClip(mcr) => {
151+
if let Some(obj) = mcr.coerce_to_object(activation) {
152+
self.print_object(obj, activation)
153+
} else {
154+
self.output.push_str("undefined")
155+
}
153156
}
154157
}
155158
}

core/src/avm1/globals/movie_clip.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,7 +1595,7 @@ fn load_movie<'gc>(
15951595
let url = url_val.coerce_to_string(activation)?;
15961596
let method = args.get(1).cloned().unwrap_or(Value::Undefined);
15971597
let method = NavigationMethod::from_method_str(&method.coerce_to_string(activation)?);
1598-
let target_obj = target.object1_or_undef().coerce_to_object(activation);
1598+
let target_obj = target.object1_or_bare(activation.gc());
15991599
let request = activation.object_into_request(target_obj, url, method);
16001600
let future = activation.context.load_manager.load_movie_into_clip(
16011601
activation.context.player_handle(),
@@ -1618,7 +1618,7 @@ fn load_variables<'gc>(
16181618
let url = url_val.coerce_to_string(activation)?;
16191619
let method = args.get(1).cloned().unwrap_or(Value::Undefined);
16201620
let method = NavigationMethod::from_method_str(&method.coerce_to_string(activation)?);
1621-
let target = target.object1_or_undef().coerce_to_object(activation);
1621+
let target = target.object1_or_bare(activation.gc());
16221622
let request = activation.object_into_request(target, url, method);
16231623
let future = crate::loader::load_form_into_object(activation.context, target, request);
16241624
activation.context.navigator.spawn_future(future);

core/src/avm1/object/stage_object.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ fn resolve_path_property<'gc>(
156156
} else if name.eq_with_case(b"_parent", case_sensitive) {
157157
return Some(
158158
dobj.avm1_parent()
159-
.map(|dn| dn.object1_or_undef().coerce_to_object(activation))
159+
.map(|dn| dn.object1_or_bare(activation.gc()))
160160
.map(Value::Object)
161161
.unwrap_or(Value::Undefined),
162162
);

core/src/avm1/object_reference.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,9 +167,7 @@ impl<'gc> MovieClipReference<'gc> {
167167

168168
Some((
169169
false,
170-
display_object
171-
.object1_or_undef()
172-
.coerce_to_object(activation),
170+
display_object.object1_or_bare(activation.gc()),
173171
display_object,
174172
))
175173
} else {

core/src/avm1/runtime.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -146,15 +146,14 @@ impl<'gc> Avm1<'gc> {
146146
return;
147147
}
148148

149-
let mut parent_activation = Activation::from_nothing(
149+
// TODO(moulins): remove this activation, it's useless.
150+
let parent_activation = Activation::from_nothing(
150151
context,
151152
ActivationIdentifier::root("[Actions Parent]"),
152153
active_clip,
153154
);
154155

155-
let clip_obj = active_clip
156-
.object1_or_undef()
157-
.coerce_to_object(&mut parent_activation);
156+
let clip_obj = active_clip.object1_or_bare(parent_activation.gc());
158157
let child_scope = Gc::new(
159158
parent_activation.gc(),
160159
Scope::new(
@@ -231,15 +230,14 @@ impl<'gc> Avm1<'gc> {
231230
return;
232231
}
233232

234-
let mut parent_activation = Activation::from_nothing(
233+
// TODO(moulins): remove this activation, it's useless
234+
let parent_activation = Activation::from_nothing(
235235
context,
236236
ActivationIdentifier::root("[Init Parent]"),
237237
active_clip,
238238
);
239239

240-
let clip_obj = active_clip
241-
.object1_or_undef()
242-
.coerce_to_object(&mut parent_activation);
240+
let clip_obj = active_clip.object1_or_bare(parent_activation.gc());
243241
let child_scope = Gc::new(
244242
parent_activation.gc(),
245243
Scope::new(

core/src/avm1/scope.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,9 @@ impl<'gc> Scope<'gc> {
158158
&& self.locals().has_own_property(activation, name)
159159
{
160160
return activation
161-
.root_object()
162-
.coerce_to_object(activation)
161+
.base_clip()
162+
.avm1_root()
163+
.object1_or_bare(activation.gc())
163164
.get_non_slash_path(name, activation)
164165
.map(|v| CallableValue::Callable(self.locals_cell(), v));
165166
}

core/src/display_object.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2530,6 +2530,15 @@ pub trait TDisplayObject<'gc>:
25302530
.unwrap_or(Avm1Value::Undefined)
25312531
}
25322532

2533+
// [MOULINS]: I suspect that most (if not all) usages of this method are incorrect,
2534+
// but a dedicated method is still superior to the equivalent `self.object1_or_undef().coerce_to_object()`
2535+
// as it avoids the need for an activation.
2536+
#[no_dynamic]
2537+
fn object1_or_bare(self, mc: &Mutation<'gc>) -> Avm1Object<'gc> {
2538+
self.object1()
2539+
.unwrap_or_else(|| Avm1Object::new_without_proto(mc))
2540+
}
2541+
25332542
fn object2(self) -> Option<Avm2StageObject<'gc>>;
25342543

25352544
fn set_object2(self, _context: &mut UpdateContext<'gc>, _to: Avm2StageObject<'gc>) {}

0 commit comments

Comments
 (0)