Skip to content

Commit a4749c1

Browse files
committed
core: Do not panic on missing parent in text variable binding
Turns out that sometimes try_bind_text_field_variable is executed when we don't have a parent.
1 parent a546909 commit a4749c1

File tree

1 file changed

+59
-59
lines changed

1 file changed

+59
-59
lines changed

core/src/display_object/edit_text.rs

+59-59
Original file line numberDiff line numberDiff line change
@@ -1370,74 +1370,74 @@ impl<'gc> EditText<'gc> {
13701370
activation: &mut Avm1Activation<'_, 'gc>,
13711371
set_initial_value: bool,
13721372
) -> bool {
1373-
if let Some(var_path) = self.variable() {
1374-
let mut bound = false;
1373+
let Some(var_path) = self.variable() else {
1374+
// No variable for this text field; success by default
1375+
return true;
1376+
};
13751377

1376-
// Any previous binding should have been cleared.
1377-
debug_assert!(self.0.read().bound_stage_object.is_none());
1378+
// Any previous binding should have been cleared.
1379+
debug_assert!(self.0.read().bound_stage_object.is_none());
13781380

1379-
// Avoid double-borrows by copying the string.
1380-
// TODO: Can we avoid this somehow? Maybe when we have a better string type.
1381-
let variable_path = WString::from_utf8(&var_path);
1382-
drop(var_path);
1381+
// Avoid double-borrows by copying the string.
1382+
// TODO: Can we avoid this somehow? Maybe when we have a better string type.
1383+
let variable_path = WString::from_utf8(&var_path);
1384+
drop(var_path);
13831385

1384-
let mut parent = self.avm1_parent().unwrap();
1385-
while parent.as_avm1_button().is_some() {
1386-
parent = parent.avm1_parent().unwrap();
1387-
}
1386+
let Some(mut parent) = self.avm1_parent() else {
1387+
return false;
1388+
};
1389+
while parent.as_avm1_button().is_some() {
1390+
let Some(p) = parent.avm1_parent() else {
1391+
return false;
1392+
};
1393+
parent = p;
1394+
}
13881395

1389-
activation.run_with_child_frame_for_display_object(
1390-
"[Text Field Binding]",
1391-
parent,
1392-
self.movie().version(),
1393-
|activation| {
1394-
if let Ok(Some((object, property))) =
1395-
activation.resolve_variable_path(parent, &variable_path)
1396-
{
1397-
let property = AvmString::new(activation.gc(), property);
1398-
1399-
// If this text field was just created, we immediately propagate the text to the variable (or vice versa).
1400-
if set_initial_value {
1401-
// If the property exists on the object, we overwrite the text with the property's value.
1402-
if object.has_property(activation, property) {
1403-
let value = object.get(property, activation).unwrap();
1404-
self.set_html_text(
1405-
&value
1406-
.coerce_to_string(activation)
1407-
.unwrap_or_else(|_| istr!("")),
1408-
activation.context,
1396+
let mut bound = false;
1397+
activation.run_with_child_frame_for_display_object(
1398+
"[Text Field Binding]",
1399+
parent,
1400+
self.movie().version(),
1401+
|activation| {
1402+
if let Ok(Some((object, property))) =
1403+
activation.resolve_variable_path(parent, &variable_path)
1404+
{
1405+
let property = AvmString::new(activation.gc(), property);
1406+
1407+
// If this text field was just created, we immediately propagate the text to the variable (or vice versa).
1408+
if set_initial_value {
1409+
// If the property exists on the object, we overwrite the text with the property's value.
1410+
if object.has_property(activation, property) {
1411+
let value = object.get(property, activation).unwrap();
1412+
self.set_html_text(
1413+
&value
1414+
.coerce_to_string(activation)
1415+
.unwrap_or_else(|_| istr!("")),
1416+
activation.context,
1417+
);
1418+
} else {
1419+
// Otherwise, we initialize the property with the text field's text, if it's non-empty.
1420+
// Note that HTML text fields are often initialized with an empty <p> tag, which is not considered empty.
1421+
let text = self.text();
1422+
if !text.is_empty() {
1423+
let _ = object.set(
1424+
property,
1425+
AvmString::new(activation.gc(), self.text()).into(),
1426+
activation,
14091427
);
1410-
} else {
1411-
// Otherwise, we initialize the property with the text field's text, if it's non-empty.
1412-
// Note that HTML text fields are often initialized with an empty <p> tag, which is not considered empty.
1413-
let text = self.text();
1414-
if !text.is_empty() {
1415-
let _ = object.set(
1416-
property,
1417-
AvmString::new(activation.gc(), self.text()).into(),
1418-
activation,
1419-
);
1420-
}
14211428
}
14221429
}
1430+
}
14231431

1424-
if let Some(stage_object) = object.as_stage_object() {
1425-
self.0.write(activation.gc()).bound_stage_object = Some(stage_object);
1426-
stage_object.register_text_field_binding(
1427-
activation.gc(),
1428-
self,
1429-
property,
1430-
);
1431-
bound = true;
1432-
}
1432+
if let Some(stage_object) = object.as_stage_object() {
1433+
self.0.write(activation.gc()).bound_stage_object = Some(stage_object);
1434+
stage_object.register_text_field_binding(activation.gc(), self, property);
1435+
bound = true;
14331436
}
1434-
},
1435-
);
1436-
bound
1437-
} else {
1438-
// No variable for this text field; success by default
1439-
true
1440-
}
1437+
}
1438+
},
1439+
);
1440+
bound
14411441
}
14421442

14431443
/// Unsets a bound display object from this text field.

0 commit comments

Comments
 (0)