avm2: Ignore duplicate definitions

This commit is contained in:
EmperorBale 2023-02-23 02:48:19 -08:00 committed by Bale
parent 01af1af4d9
commit 5bc3c696b5
4 changed files with 21 additions and 33 deletions

View File

@ -182,25 +182,18 @@ impl<'gc> Domain<'gc> {
/// Export a definition from a script into the current application domain. /// Export a definition from a script into the current application domain.
/// ///
/// This returns an error if the name is already defined in the current or /// This does nothing if the definition already exists.
/// any parent domains.
pub fn export_definition( pub fn export_definition(
&mut self, &mut self,
name: QName<'gc>, name: QName<'gc>,
script: Script<'gc>, script: Script<'gc>,
mc: MutationContext<'gc, '_>, mc: MutationContext<'gc, '_>,
) -> Result<(), Error<'gc>> { ) {
if self.has_definition(name) { if self.has_definition(name) {
return Err(format!( return;
"VerifyError: Attempted to redefine existing name {}",
name.local_name()
)
.into());
} }
self.0.write(mc).defs.insert(name, script); self.0.write(mc).defs.insert(name, script);
Ok(())
} }
pub fn export_class( pub fn export_class(
@ -208,9 +201,8 @@ impl<'gc> Domain<'gc> {
name: QName<'gc>, name: QName<'gc>,
class: GcCell<'gc, Class<'gc>>, class: GcCell<'gc, Class<'gc>>,
mc: MutationContext<'gc, '_>, mc: MutationContext<'gc, '_>,
) -> Result<(), Error<'gc>> { ) {
self.0.write(mc).classes.insert(name, class); self.0.write(mc).classes.insert(name, class);
Ok(())
} }
pub fn domain_memory(&self) -> ByteArrayObject<'gc> { pub fn domain_memory(&self) -> ByteArrayObject<'gc> {

View File

@ -218,7 +218,7 @@ fn function<'gc>(
); );
let method = Method::from_builtin(nf, name, mc); let method = Method::from_builtin(nf, name, mc);
let as3fn = FunctionObject::from_method(activation, method, scope, None, None).into(); let as3fn = FunctionObject::from_method(activation, method, scope, None, None).into();
domain.export_definition(qname, script, mc)?; domain.export_definition(qname, script, mc);
global.install_const_late(mc, qname, as3fn, activation.avm2().classes().function); global.install_const_late(mc, qname, as3fn, activation.avm2().classes().function);
Ok(()) Ok(())
@ -234,7 +234,7 @@ fn dynamic_class<'gc>(
script: Script<'gc>, script: Script<'gc>,
// The `ClassObject` of the `Class` class // The `ClassObject` of the `Class` class
class_class: ClassObject<'gc>, class_class: ClassObject<'gc>,
) -> Result<(), Error<'gc>> { ) {
let (_, mut global, mut domain) = script.init(); let (_, mut global, mut domain) = script.init();
let class = class_object.inner_class_definition(); let class = class_object.inner_class_definition();
let name = class.read().name(); let name = class.read().name();
@ -290,8 +290,8 @@ fn class<'gc>(
class_object.into(), class_object.into(),
activation.avm2().classes().class, activation.avm2().classes().class,
); );
domain.export_definition(class_name, script, activation.context.gc_context)?; domain.export_definition(class_name, script, activation.context.gc_context);
domain.export_class(class_name, class_def, activation.context.gc_context)?; domain.export_class(class_name, class_def, activation.context.gc_context);
Ok(class_object) Ok(class_object)
} }
@ -397,9 +397,9 @@ pub fn load_player_globals<'gc>(
// From this point, `globals` is safe to be modified // From this point, `globals` is safe to be modified
dynamic_class(mc, object_class, script, class_class)?; dynamic_class(mc, object_class, script, class_class);
dynamic_class(mc, fn_class, script, class_class)?; dynamic_class(mc, fn_class, script, class_class);
dynamic_class(mc, class_class, script, class_class)?; dynamic_class(mc, class_class, script, class_class);
// After this point, it is safe to initialize any other classes. // After this point, it is safe to initialize any other classes.
// Make sure to initialize superclasses *before* their subclasses! // Make sure to initialize superclasses *before* their subclasses!

View File

@ -123,7 +123,7 @@ pub fn class_init<'gc>(
int_vector_class.into(), int_vector_class.into(),
class_class, class_class,
); );
domain.export_definition(int_vector_name, script, activation.context.gc_context)?; domain.export_definition(int_vector_name, script, activation.context.gc_context);
let uint_class = activation.avm2().classes().uint; let uint_class = activation.avm2().classes().uint;
let uint_vector_class = this.apply(activation, &[uint_class.into()])?; let uint_vector_class = this.apply(activation, &[uint_class.into()])?;
@ -139,7 +139,7 @@ pub fn class_init<'gc>(
uint_vector_class.into(), uint_vector_class.into(),
class_class, class_class,
); );
domain.export_definition(uint_vector_name, script, activation.context.gc_context)?; domain.export_definition(uint_vector_name, script, activation.context.gc_context);
let number_class = activation.avm2().classes().number; let number_class = activation.avm2().classes().number;
let number_vector_class = this.apply(activation, &[number_class.into()])?; let number_vector_class = this.apply(activation, &[number_class.into()])?;
@ -155,7 +155,7 @@ pub fn class_init<'gc>(
number_vector_class.into(), number_vector_class.into(),
class_class, class_class,
); );
domain.export_definition(number_vector_name, script, activation.context.gc_context)?; domain.export_definition(number_vector_name, script, activation.context.gc_context);
let object_vector_class = this.apply(activation, &[Value::Null])?; let object_vector_class = this.apply(activation, &[Value::Null])?;
let object_vector_name = QName::new(vector_internal_namespace, "Vector$object"); let object_vector_name = QName::new(vector_internal_namespace, "Vector$object");
@ -170,7 +170,7 @@ pub fn class_init<'gc>(
object_vector_class.into(), object_vector_class.into(),
class_class, class_class,
); );
domain.export_definition(object_vector_name, script, activation.context.gc_context)?; domain.export_definition(object_vector_name, script, activation.context.gc_context);
} }
Ok(Value::Undefined) Ok(Value::Undefined)

View File

@ -462,17 +462,13 @@ impl<'gc> Script<'gc> {
for abc_trait in script.traits.iter() { for abc_trait in script.traits.iter() {
let newtrait = Trait::from_abc_trait(unit, abc_trait, activation)?; let newtrait = Trait::from_abc_trait(unit, abc_trait, activation)?;
write.domain.export_definition( write
newtrait.name(), .domain
*self, .export_definition(newtrait.name(), *self, activation.context.gc_context);
activation.context.gc_context,
)?;
if let TraitKind::Class { class, .. } = newtrait.kind() { if let TraitKind::Class { class, .. } = newtrait.kind() {
write.domain.export_class( write
newtrait.name(), .domain
*class, .export_class(newtrait.name(), *class, activation.context.gc_context);
activation.context.gc_context,
)?;
} }
write.traits.push(newtrait); write.traits.push(newtrait);