Functions close over the constant pool they were defined with.
This commit is contained in:
parent
71d9655f6d
commit
681b4adfa4
|
@ -51,8 +51,9 @@ pub struct Avm1<'gc> {
|
|||
/// The Flash Player version we're emulating.
|
||||
player_version: u8,
|
||||
|
||||
/// The currently installed constant pool.
|
||||
constant_pool: Vec<String>,
|
||||
/// The constant pool to use for new activations from code sources that
|
||||
/// don't close over the constant pool they were defined with.
|
||||
constant_pool: GcCell<'gc, Vec<String>>,
|
||||
|
||||
/// The global object.
|
||||
globals: Object<'gc>,
|
||||
|
@ -78,6 +79,7 @@ unsafe impl<'gc> gc_arena::Collect for Avm1<'gc> {
|
|||
#[inline]
|
||||
fn trace(&self, cc: gc_arena::CollectionContext) {
|
||||
self.globals.trace(cc);
|
||||
self.constant_pool.trace(cc);
|
||||
self.prototypes.trace(cc);
|
||||
self.display_properties.trace(cc);
|
||||
self.stack_frames.trace(cc);
|
||||
|
@ -97,7 +99,7 @@ impl<'gc> Avm1<'gc> {
|
|||
|
||||
Self {
|
||||
player_version,
|
||||
constant_pool: vec![],
|
||||
constant_pool: GcCell::allocate(gc_context, vec![]),
|
||||
globals,
|
||||
prototypes,
|
||||
display_properties: stage_object::DisplayPropertyMap::new(gc_context),
|
||||
|
@ -170,7 +172,14 @@ impl<'gc> Avm1<'gc> {
|
|||
);
|
||||
self.stack_frames.push(GcCell::allocate(
|
||||
action_context.gc_context,
|
||||
Activation::from_action(swf_version, code, child_scope, clip_obj, None),
|
||||
Activation::from_action(
|
||||
swf_version,
|
||||
code,
|
||||
child_scope,
|
||||
self.constant_pool,
|
||||
clip_obj,
|
||||
None,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -197,7 +206,14 @@ impl<'gc> Avm1<'gc> {
|
|||
self.push(Value::Undefined);
|
||||
self.stack_frames.push(GcCell::allocate(
|
||||
action_context.gc_context,
|
||||
Activation::from_action(swf_version, code, child_scope, clip_obj, None),
|
||||
Activation::from_action(
|
||||
swf_version,
|
||||
code,
|
||||
child_scope,
|
||||
self.constant_pool,
|
||||
clip_obj,
|
||||
None,
|
||||
),
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -831,10 +847,18 @@ impl<'gc> Avm1<'gc> {
|
|||
|
||||
fn action_constant_pool(
|
||||
&mut self,
|
||||
_context: &mut UpdateContext,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
constant_pool: &[&str],
|
||||
) -> Result<(), Error> {
|
||||
self.constant_pool = constant_pool.iter().map(|s| s.to_string()).collect();
|
||||
self.constant_pool = GcCell::allocate(
|
||||
context.gc_context,
|
||||
constant_pool.iter().map(|s| s.to_string()).collect(),
|
||||
);
|
||||
self.current_stack_frame()
|
||||
.unwrap()
|
||||
.write(context.gc_context)
|
||||
.set_constant_pool(self.constant_pool);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -863,7 +887,9 @@ impl<'gc> Avm1<'gc> {
|
|||
self.current_stack_frame().unwrap().read().scope_cell(),
|
||||
context.gc_context,
|
||||
);
|
||||
let func = Avm1Function::from_df1(swf_version, func_data, name, params, scope);
|
||||
let constant_pool = self.current_stack_frame().unwrap().read().constant_pool();
|
||||
let func =
|
||||
Avm1Function::from_df1(swf_version, func_data, name, params, scope, constant_pool);
|
||||
let prototype =
|
||||
ScriptObject::object(context.gc_context, Some(self.prototypes.object)).into();
|
||||
let func_obj = ScriptObject::function(
|
||||
|
@ -901,7 +927,9 @@ impl<'gc> Avm1<'gc> {
|
|||
self.current_stack_frame().unwrap().read().scope_cell(),
|
||||
context.gc_context,
|
||||
);
|
||||
let func = Avm1Function::from_df2(swf_version, func_data, action_func, scope);
|
||||
let constant_pool = self.current_stack_frame().unwrap().read().constant_pool();
|
||||
let func =
|
||||
Avm1Function::from_df2(swf_version, func_data, action_func, scope, constant_pool);
|
||||
let prototype =
|
||||
ScriptObject::object(context.gc_context, Some(self.prototypes.object)).into();
|
||||
let func_obj = ScriptObject::function(
|
||||
|
@ -1634,13 +1662,25 @@ impl<'gc> Avm1<'gc> {
|
|||
SwfValue::Str(v) => v.to_string().into(),
|
||||
SwfValue::Register(v) => self.current_register(*v),
|
||||
SwfValue::ConstantPool(i) => {
|
||||
if let Some(value) = self.constant_pool.get(*i as usize) {
|
||||
if let Some(value) = self
|
||||
.current_stack_frame()
|
||||
.unwrap()
|
||||
.read()
|
||||
.constant_pool()
|
||||
.read()
|
||||
.get(*i as usize)
|
||||
{
|
||||
value.to_string().into()
|
||||
} else {
|
||||
log::warn!(
|
||||
"ActionPush: Constant pool index {} out of range (len = {})",
|
||||
i,
|
||||
self.constant_pool.len()
|
||||
self.current_stack_frame()
|
||||
.unwrap()
|
||||
.read()
|
||||
.constant_pool()
|
||||
.read()
|
||||
.len()
|
||||
);
|
||||
Value::Undefined
|
||||
}
|
||||
|
|
|
@ -66,6 +66,9 @@ pub struct Activation<'gc> {
|
|||
/// All defined local variables in this stack frame.
|
||||
scope: GcCell<'gc, Scope<'gc>>,
|
||||
|
||||
/// The currently in use constant pool.
|
||||
constant_pool: GcCell<'gc, Vec<String>>,
|
||||
|
||||
/// The immutable value of `this`.
|
||||
this: Object<'gc>,
|
||||
|
||||
|
@ -114,6 +117,7 @@ impl<'gc> Activation<'gc> {
|
|||
swf_version: u8,
|
||||
code: SwfSlice,
|
||||
scope: GcCell<'gc, Scope<'gc>>,
|
||||
constant_pool: GcCell<'gc, Vec<String>>,
|
||||
this: Object<'gc>,
|
||||
arguments: Option<Object<'gc>>,
|
||||
) -> Activation<'gc> {
|
||||
|
@ -122,6 +126,7 @@ impl<'gc> Activation<'gc> {
|
|||
data: code,
|
||||
pc: 0,
|
||||
scope,
|
||||
constant_pool,
|
||||
this,
|
||||
arguments,
|
||||
return_value: None,
|
||||
|
@ -135,6 +140,7 @@ impl<'gc> Activation<'gc> {
|
|||
swf_version: u8,
|
||||
code: SwfSlice,
|
||||
scope: GcCell<'gc, Scope<'gc>>,
|
||||
constant_pool: GcCell<'gc, Vec<String>>,
|
||||
this: Object<'gc>,
|
||||
arguments: Option<Object<'gc>>,
|
||||
) -> Activation<'gc> {
|
||||
|
@ -143,6 +149,7 @@ impl<'gc> Activation<'gc> {
|
|||
data: code,
|
||||
pc: 0,
|
||||
scope,
|
||||
constant_pool,
|
||||
this,
|
||||
arguments,
|
||||
return_value: None,
|
||||
|
@ -166,6 +173,7 @@ impl<'gc> Activation<'gc> {
|
|||
) -> Activation<'gc> {
|
||||
let global_scope = GcCell::allocate(mc, Scope::from_global_object(globals));
|
||||
let child_scope = GcCell::allocate(mc, Scope::new_local_scope(global_scope, mc));
|
||||
let empty_constant_pool = GcCell::allocate(mc, Vec::new());
|
||||
|
||||
Activation {
|
||||
swf_version,
|
||||
|
@ -176,6 +184,7 @@ impl<'gc> Activation<'gc> {
|
|||
},
|
||||
pc: 0,
|
||||
scope: child_scope,
|
||||
constant_pool: empty_constant_pool,
|
||||
this: globals,
|
||||
arguments: None,
|
||||
return_value: None,
|
||||
|
@ -192,6 +201,7 @@ impl<'gc> Activation<'gc> {
|
|||
data: code,
|
||||
pc: 0,
|
||||
scope,
|
||||
constant_pool: self.constant_pool,
|
||||
this: self.this,
|
||||
arguments: self.arguments,
|
||||
return_value: None,
|
||||
|
@ -342,6 +352,14 @@ impl<'gc> Activation<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn constant_pool(&self) -> GcCell<'gc, Vec<String>> {
|
||||
self.constant_pool
|
||||
}
|
||||
|
||||
pub fn set_constant_pool(&mut self, constant_pool: GcCell<'gc, Vec<String>>) {
|
||||
self.constant_pool = constant_pool;
|
||||
}
|
||||
|
||||
/// Attempts to lock the activation frame for execution.
|
||||
///
|
||||
/// If this frame is already executing, that is an error condition.
|
||||
|
|
|
@ -66,6 +66,9 @@ pub struct Avm1Function<'gc> {
|
|||
|
||||
/// The scope the function was born into.
|
||||
scope: GcCell<'gc, Scope<'gc>>,
|
||||
|
||||
/// The constant pool the function executes with.
|
||||
constant_pool: GcCell<'gc, Vec<String>>,
|
||||
}
|
||||
|
||||
impl<'gc> Avm1Function<'gc> {
|
||||
|
@ -79,6 +82,7 @@ impl<'gc> Avm1Function<'gc> {
|
|||
name: &str,
|
||||
params: &[&str],
|
||||
scope: GcCell<'gc, Scope<'gc>>,
|
||||
constant_pool: GcCell<'gc, Vec<String>>,
|
||||
) -> Self {
|
||||
let name = match name {
|
||||
"" => None,
|
||||
|
@ -101,6 +105,7 @@ impl<'gc> Avm1Function<'gc> {
|
|||
preload_global: false,
|
||||
params: params.iter().map(|s| (None, s.to_string())).collect(),
|
||||
scope,
|
||||
constant_pool,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,6 +115,7 @@ impl<'gc> Avm1Function<'gc> {
|
|||
actions: SwfSlice,
|
||||
swf_function: &swf::avm1::types::Function,
|
||||
scope: GcCell<'gc, Scope<'gc>>,
|
||||
constant_pool: GcCell<'gc, Vec<String>>,
|
||||
) -> Self {
|
||||
let name = match swf_function.name {
|
||||
"" => None,
|
||||
|
@ -141,6 +147,7 @@ impl<'gc> Avm1Function<'gc> {
|
|||
preload_global: swf_function.preload_global,
|
||||
params: owned_params,
|
||||
scope,
|
||||
constant_pool,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,6 +244,7 @@ impl<'gc> Executable<'gc> {
|
|||
effective_ver,
|
||||
af.data(),
|
||||
child_scope,
|
||||
af.constant_pool,
|
||||
this,
|
||||
Some(argcell),
|
||||
),
|
||||
|
|
Loading…
Reference in New Issue