ES4 classes, while superficially similar to functions, are not functions and should not inherit from the `Function` prototype.
We still reuse the `FunctionObject` machinery internally. If necessary, we may want to split this into a separate `ClassObject` if some internal `TObject` method needs replacing for classes.
This commit is contained in:
parent
8b36751fbb
commit
4b66af8dc3
|
@ -308,6 +308,7 @@ impl<'gc> FunctionObject<'gc> {
|
||||||
});
|
});
|
||||||
let mut class_proto = super_proto?.derive(avm, context, class.clone(), scope)?;
|
let mut class_proto = super_proto?.derive(avm, context, class.clone(), scope)?;
|
||||||
let fn_proto = avm.prototypes().function;
|
let fn_proto = avm.prototypes().function;
|
||||||
|
let class_constr_proto = avm.prototypes().class;
|
||||||
|
|
||||||
let initializer_index = class.instance().init_method.clone();
|
let initializer_index = class.instance().init_method.clone();
|
||||||
let initializer: Result<Avm2MethodEntry, Error> =
|
let initializer: Result<Avm2MethodEntry, Error> =
|
||||||
|
@ -358,7 +359,7 @@ impl<'gc> FunctionObject<'gc> {
|
||||||
context.gc_context,
|
context.gc_context,
|
||||||
class_initializer?,
|
class_initializer?,
|
||||||
scope,
|
scope,
|
||||||
fn_proto,
|
class_constr_proto,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::avm2::{Avm2, Error};
|
||||||
use crate::context::UpdateContext;
|
use crate::context::UpdateContext;
|
||||||
use gc_arena::{Collect, MutationContext};
|
use gc_arena::{Collect, MutationContext};
|
||||||
|
|
||||||
|
mod class;
|
||||||
mod flash;
|
mod flash;
|
||||||
mod function;
|
mod function;
|
||||||
mod object;
|
mod object;
|
||||||
|
@ -33,6 +34,7 @@ fn trace<'gc>(
|
||||||
pub struct SystemPrototypes<'gc> {
|
pub struct SystemPrototypes<'gc> {
|
||||||
pub object: Object<'gc>,
|
pub object: Object<'gc>,
|
||||||
pub function: Object<'gc>,
|
pub function: Object<'gc>,
|
||||||
|
pub class: Object<'gc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a free-function builtin to the global scope.
|
/// Add a free-function builtin to the global scope.
|
||||||
|
@ -86,6 +88,7 @@ pub fn construct_global_scope<'gc>(
|
||||||
// public / root package
|
// public / root package
|
||||||
let object_proto = ScriptObject::bare_object(mc);
|
let object_proto = ScriptObject::bare_object(mc);
|
||||||
let fn_proto = function::create_proto(mc, object_proto);
|
let fn_proto = function::create_proto(mc, object_proto);
|
||||||
|
let class_proto = class::create_proto(mc, object_proto, fn_proto);
|
||||||
|
|
||||||
object::fill_proto(mc, object_proto, fn_proto);
|
object::fill_proto(mc, object_proto, fn_proto);
|
||||||
|
|
||||||
|
@ -107,6 +110,15 @@ pub fn construct_global_scope<'gc>(
|
||||||
fn_proto,
|
fn_proto,
|
||||||
fn_proto,
|
fn_proto,
|
||||||
);
|
);
|
||||||
|
class(
|
||||||
|
mc,
|
||||||
|
gs,
|
||||||
|
"",
|
||||||
|
"Class",
|
||||||
|
class::constructor,
|
||||||
|
class_proto,
|
||||||
|
fn_proto,
|
||||||
|
);
|
||||||
function(mc, gs, "", "trace", trace, fn_proto);
|
function(mc, gs, "", "trace", trace, fn_proto);
|
||||||
|
|
||||||
// package `flash.events`
|
// package `flash.events`
|
||||||
|
@ -183,6 +195,7 @@ pub fn construct_global_scope<'gc>(
|
||||||
let system_prototypes = SystemPrototypes {
|
let system_prototypes = SystemPrototypes {
|
||||||
object: object_proto,
|
object: object_proto,
|
||||||
function: fn_proto,
|
function: fn_proto,
|
||||||
|
class: class_proto,
|
||||||
};
|
};
|
||||||
|
|
||||||
(gs, system_prototypes)
|
(gs, system_prototypes)
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
//! `Class` builtin/prototype
|
||||||
|
|
||||||
|
use crate::avm2::object::Object;
|
||||||
|
use crate::avm2::return_value::ReturnValue;
|
||||||
|
use crate::avm2::script_object::ScriptObject;
|
||||||
|
use crate::avm2::value::Value;
|
||||||
|
use crate::avm2::{Avm2, Error};
|
||||||
|
use crate::context::UpdateContext;
|
||||||
|
use gc_arena::MutationContext;
|
||||||
|
|
||||||
|
/// Implements `Class`
|
||||||
|
///
|
||||||
|
/// Notably, you cannot construct new classes this way, so this returns an
|
||||||
|
/// error.
|
||||||
|
pub fn constructor<'gc>(
|
||||||
|
_avm: &mut Avm2<'gc>,
|
||||||
|
_action_context: &mut UpdateContext<'_, 'gc, '_>,
|
||||||
|
_this: Option<Object<'gc>>,
|
||||||
|
_args: &[Value<'gc>],
|
||||||
|
) -> Result<ReturnValue<'gc>, Error> {
|
||||||
|
Err("Classes cannot be constructed.".into())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct `Class.prototype`.
|
||||||
|
pub fn create_proto<'gc>(
|
||||||
|
mc: MutationContext<'gc, '_>,
|
||||||
|
super_proto: Object<'gc>,
|
||||||
|
_fn_proto: Object<'gc>,
|
||||||
|
) -> Object<'gc> {
|
||||||
|
ScriptObject::object(mc, super_proto)
|
||||||
|
}
|
Loading…
Reference in New Issue