avm2: All prototypes are instances of `Object`, not their own class.
This commit is contained in:
parent
c1850d0d54
commit
469f8cb9db
|
@ -76,6 +76,39 @@ pub struct ClassObjectData<'gc> {
|
|||
}
|
||||
|
||||
impl<'gc> ClassObject<'gc> {
|
||||
/// Allocate the prototype for this class.
|
||||
///
|
||||
/// This function is not used during the initialization of "early classes",
|
||||
/// i.e. `Object`, `Function`, and `Class`. Those classes and their
|
||||
/// prototypes are weaved together separately.
|
||||
///
|
||||
/// The returned prototype will be an instance of `Object` (and thus not
|
||||
/// have this class's instance traits), but will be allocated by this
|
||||
/// class's instance allocator.
|
||||
fn allocate_prototype(
|
||||
self,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
superclass_object: Option<ClassObject<'gc>>,
|
||||
) -> Result<Object<'gc>, Error> {
|
||||
let instance_allocator = self.0.read().instance_allocator.clone();
|
||||
|
||||
if let Some(superclass_object) = superclass_object {
|
||||
let base_proto = superclass_object
|
||||
.get_property(
|
||||
superclass_object.into(),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
|
||||
//NOTE: If we do not use `instance_allocator` here, then Vector
|
||||
//enumeration will break.
|
||||
(instance_allocator.0)(activation.avm2().classes().object, base_proto, activation)
|
||||
} else {
|
||||
Ok(ScriptObject::bare_object(activation.context.gc_context))
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a class.
|
||||
///
|
||||
/// This function returns the class constructor object, which should be
|
||||
|
@ -91,22 +124,7 @@ impl<'gc> ClassObject<'gc> {
|
|||
superclass_object: Option<ClassObject<'gc>>,
|
||||
) -> Result<Self, Error> {
|
||||
let class_object = Self::from_class_partial(activation, class, superclass_object)?;
|
||||
|
||||
//TODO: Class prototypes are *not* instances of their class and should
|
||||
//not be allocated by the class allocator, but instead should be
|
||||
//regular objects
|
||||
let class_proto = if let Some(superclass_object) = superclass_object {
|
||||
let base_proto = superclass_object
|
||||
.get_property(
|
||||
superclass_object.into(),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
ScriptObject::object(activation.context.gc_context, base_proto)
|
||||
} else {
|
||||
ScriptObject::bare_object(activation.context.gc_context)
|
||||
};
|
||||
let class_proto = class_object.allocate_prototype(activation, superclass_object)?;
|
||||
|
||||
class_object.link_prototype(activation, class_proto)?;
|
||||
|
||||
|
@ -873,21 +891,7 @@ impl<'gc> TObject<'gc> for ClassObject<'gc> {
|
|||
let instance_allocator = self.0.read().instance_allocator.clone();
|
||||
let superclass_object = self.0.read().superclass_object;
|
||||
|
||||
//TODO: Class prototypes are *not* instances of their class and should
|
||||
//not be allocated by the class allocator, but instead should be
|
||||
//regular objects
|
||||
let class_proto = if let Some(superclass_object) = superclass_object {
|
||||
let base_proto = superclass_object
|
||||
.get_property(
|
||||
superclass_object.into(),
|
||||
&QName::new(Namespace::public(), "prototype").into(),
|
||||
activation,
|
||||
)?
|
||||
.coerce_to_object(activation)?;
|
||||
(instance_allocator.0)(superclass_object, base_proto, activation)?
|
||||
} else {
|
||||
ScriptObject::bare_object(activation.context.gc_context)
|
||||
};
|
||||
let class_proto = self.allocate_prototype(activation, superclass_object)?;
|
||||
|
||||
let class_class = activation.avm2().classes().class;
|
||||
let class_class_proto = activation.avm2().prototypes().class;
|
||||
|
|
|
@ -97,4 +97,40 @@ trace("//y instanceof ITest3");
|
|||
trace(y instanceof ITest3);
|
||||
|
||||
trace("//y instanceof Test4");
|
||||
trace(y instanceof Test4);
|
||||
trace(y instanceof Test4);
|
||||
|
||||
trace("//Test3.prototype instanceof Object");
|
||||
trace(Test3.prototype instanceof Object);
|
||||
|
||||
trace("//Test3.prototype instanceof Test2");
|
||||
trace(Test3.prototype instanceof Test2);
|
||||
|
||||
trace("//Test3.prototype instanceof ITest2");
|
||||
trace(Test3.prototype instanceof ITest2);
|
||||
|
||||
trace("//Test3.prototype instanceof Test3");
|
||||
trace(Test3.prototype instanceof Test3);
|
||||
|
||||
trace("//Test3.prototype instanceof ITest3");
|
||||
trace(Test3.prototype instanceof ITest3);
|
||||
|
||||
trace("//Test3.prototype instanceof Test4");
|
||||
trace(Test3.prototype instanceof Test4);
|
||||
|
||||
trace("//Test4.prototype instanceof Object");
|
||||
trace(Test4.prototype instanceof Object);
|
||||
|
||||
trace("//Test4.prototype instanceof Test2");
|
||||
trace(Test4.prototype instanceof Test2);
|
||||
|
||||
trace("//Test4.prototype instanceof ITest2");
|
||||
trace(Test4.prototype instanceof ITest2);
|
||||
|
||||
trace("//Test4.prototype instanceof Test3");
|
||||
trace(Test4.prototype instanceof Test3);
|
||||
|
||||
trace("//Test4.prototype instanceof ITest3");
|
||||
trace(Test4.prototype instanceof ITest3);
|
||||
|
||||
trace("//Test4.prototype instanceof Test4");
|
||||
trace(Test4.prototype instanceof Test4);
|
|
@ -22,3 +22,27 @@ true
|
|||
false
|
||||
//y instanceof Test4
|
||||
true
|
||||
//Test3.prototype instanceof Object
|
||||
true
|
||||
//Test3.prototype instanceof Test2
|
||||
true
|
||||
//Test3.prototype instanceof ITest2
|
||||
false
|
||||
//Test3.prototype instanceof Test3
|
||||
false
|
||||
//Test3.prototype instanceof ITest3
|
||||
false
|
||||
//Test3.prototype instanceof Test4
|
||||
false
|
||||
//Test4.prototype instanceof Object
|
||||
true
|
||||
//Test4.prototype instanceof Test2
|
||||
true
|
||||
//Test4.prototype instanceof ITest2
|
||||
false
|
||||
//Test4.prototype instanceof Test3
|
||||
true
|
||||
//Test4.prototype instanceof ITest3
|
||||
false
|
||||
//Test4.prototype instanceof Test4
|
||||
false
|
||||
|
|
Binary file not shown.
|
@ -97,4 +97,40 @@ trace("//y is ITest3");
|
|||
trace(y is ITest3);
|
||||
|
||||
trace("//y is Test4");
|
||||
trace(y is Test4);
|
||||
trace(y is Test4);
|
||||
|
||||
trace("//Test3.prototype is Object");
|
||||
trace(Test3.prototype is Object);
|
||||
|
||||
trace("//Test3.prototype is Test2");
|
||||
trace(Test3.prototype is Test2);
|
||||
|
||||
trace("//Test3.prototype is ITest2");
|
||||
trace(Test3.prototype is ITest2);
|
||||
|
||||
trace("//Test3.prototype is Test3");
|
||||
trace(Test3.prototype is Test3);
|
||||
|
||||
trace("//Test3.prototype is ITest3");
|
||||
trace(Test3.prototype is ITest3);
|
||||
|
||||
trace("//Test3.prototype is Test4");
|
||||
trace(Test3.prototype is Test4);
|
||||
|
||||
trace("//Test4.prototype is Object");
|
||||
trace(Test4.prototype is Object);
|
||||
|
||||
trace("//Test4.prototype is Test2");
|
||||
trace(Test4.prototype is Test2);
|
||||
|
||||
trace("//Test4.prototype is ITest2");
|
||||
trace(Test4.prototype is ITest2);
|
||||
|
||||
trace("//Test4.prototype is Test3");
|
||||
trace(Test4.prototype is Test3);
|
||||
|
||||
trace("//Test4.prototype is ITest3");
|
||||
trace(Test4.prototype is ITest3);
|
||||
|
||||
trace("//Test4.prototype is Test4");
|
||||
trace(Test4.prototype is Test4);
|
|
@ -22,3 +22,27 @@ true
|
|||
true
|
||||
//y is Test4
|
||||
true
|
||||
//Test3.prototype is Object
|
||||
true
|
||||
//Test3.prototype is Test2
|
||||
false
|
||||
//Test3.prototype is ITest2
|
||||
false
|
||||
//Test3.prototype is Test3
|
||||
false
|
||||
//Test3.prototype is ITest3
|
||||
false
|
||||
//Test3.prototype is Test4
|
||||
false
|
||||
//Test4.prototype is Object
|
||||
true
|
||||
//Test4.prototype is Test2
|
||||
false
|
||||
//Test4.prototype is ITest2
|
||||
false
|
||||
//Test4.prototype is Test3
|
||||
false
|
||||
//Test4.prototype is ITest3
|
||||
false
|
||||
//Test4.prototype is Test4
|
||||
false
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue