avm1: don't use &str methods when parsing enum parameters in MovieClip

This commit is contained in:
Moulins 2021-09-21 22:09:46 +02:00 committed by kmeisthax
parent d850085d2b
commit 1d9d7e6942
8 changed files with 96 additions and 90 deletions

View File

@ -5,7 +5,7 @@ use crate::avm1::error::Error;
use crate::avm1::object::bevel_filter::{BevelFilterObject, BevelFilterType}; use crate::avm1::object::bevel_filter::{BevelFilterObject, BevelFilterType};
use crate::avm1::property_decl::{define_properties_on, Declaration}; use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, TObject, Value}; use crate::avm1::{Object, TObject, Value};
use crate::string::AvmString; use crate::string::{AvmString, BorrowWStr, WStr};
use gc_arena::MutationContext; use gc_arena::MutationContext;
const PROTO_DECLS: &[Declaration] = declare_properties! { const PROTO_DECLS: &[Declaration] = declare_properties! {
@ -378,8 +378,8 @@ pub fn get_type<'gc>(
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
if let Some(filter) = this.as_bevel_filter_object() { if let Some(filter) = this.as_bevel_filter_object() {
let type_: &str = filter.get_type().into(); let type_: WStr<'_> = filter.get_type().into();
return Ok(AvmString::new(activation.context.gc_context, type_.to_string()).into()); return Ok(AvmString::new_ucs2(activation.context.gc_context, type_.into()).into());
} }
Ok(Value::Undefined) Ok(Value::Undefined)
@ -394,7 +394,7 @@ pub fn set_type<'gc>(
.get(0) .get(0)
.unwrap_or(&"inner".into()) .unwrap_or(&"inner".into())
.coerce_to_string(activation) .coerce_to_string(activation)
.map(|s| s.as_str().into())?; .map(|s| s.borrow().into())?;
if let Some(filter) = this.as_bevel_filter_object() { if let Some(filter) = this.as_bevel_filter_object() {
filter.set_type(activation.context.gc_context, type_); filter.set_type(activation.context.gc_context, type_);

View File

@ -5,7 +5,7 @@ use crate::avm1::error::Error;
use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject; use crate::avm1::object::displacement_map_filter::DisplacementMapFilterObject;
use crate::avm1::property_decl::{define_properties_on, Declaration}; use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{Object, TObject, Value}; use crate::avm1::{Object, TObject, Value};
use crate::string::AvmString; use crate::string::{AvmString, BorrowWStr, WStr};
use gc_arena::MutationContext; use gc_arena::MutationContext;
const PROTO_DECLS: &[Declaration] = declare_properties! { const PROTO_DECLS: &[Declaration] = declare_properties! {
@ -224,9 +224,8 @@ pub fn mode<'gc>(
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
if let Some(object) = this.as_displacement_map_filter_object() { if let Some(object) = this.as_displacement_map_filter_object() {
return Ok( let mode: WStr<'_> = object.mode().into();
AvmString::new(activation.context.gc_context, String::from(object.mode())).into(), return Ok(AvmString::new_ucs2(activation.context.gc_context, mode.into()).into());
);
} }
Ok(Value::Undefined) Ok(Value::Undefined)
@ -243,7 +242,7 @@ pub fn set_mode<'gc>(
.coerce_to_string(activation)?; .coerce_to_string(activation)?;
if let Some(object) = this.as_displacement_map_filter_object() { if let Some(object) = this.as_displacement_map_filter_object() {
object.set_mode(activation.context.gc_context, mode.as_str().into()); object.set_mode(activation.context.gc_context, mode.borrow().into());
} }
Ok(Value::Undefined) Ok(Value::Undefined)

View File

@ -6,7 +6,7 @@ use crate::avm1::object::bevel_filter::BevelFilterType;
use crate::avm1::object::gradient_bevel_filter::GradientBevelFilterObject; use crate::avm1::object::gradient_bevel_filter::GradientBevelFilterObject;
use crate::avm1::property_decl::{define_properties_on, Declaration}; use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{ArrayObject, Object, TObject, Value}; use crate::avm1::{ArrayObject, Object, TObject, Value};
use crate::string::AvmString; use crate::string::{AvmString, BorrowWStr, WStr};
use gc_arena::MutationContext; use gc_arena::MutationContext;
const PROTO_DECLS: &[Declaration] = declare_properties! { const PROTO_DECLS: &[Declaration] = declare_properties! {
@ -392,8 +392,8 @@ pub fn get_type<'gc>(
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
if let Some(filter) = this.as_gradient_bevel_filter_object() { if let Some(filter) = this.as_gradient_bevel_filter_object() {
let type_: &str = filter.get_type().into(); let type_: WStr<'_> = filter.get_type().into();
return Ok(AvmString::new(activation.context.gc_context, type_.to_string()).into()); return Ok(AvmString::new_ucs2(activation.context.gc_context, type_.into()).into());
} }
Ok(Value::Undefined) Ok(Value::Undefined)
@ -408,7 +408,7 @@ pub fn set_type<'gc>(
.get(0) .get(0)
.unwrap_or(&"inner".into()) .unwrap_or(&"inner".into())
.coerce_to_string(activation) .coerce_to_string(activation)
.map(|s| s.as_str().into())?; .map(|s| s.borrow().into())?;
if let Some(filter) = this.as_gradient_bevel_filter_object() { if let Some(filter) = this.as_gradient_bevel_filter_object() {
filter.set_type(activation.context.gc_context, type_); filter.set_type(activation.context.gc_context, type_);

View File

@ -6,7 +6,7 @@ use crate::avm1::object::bevel_filter::BevelFilterType;
use crate::avm1::object::gradient_glow_filter::GradientGlowFilterObject; use crate::avm1::object::gradient_glow_filter::GradientGlowFilterObject;
use crate::avm1::property_decl::{define_properties_on, Declaration}; use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{ArrayObject, Object, TObject, Value}; use crate::avm1::{ArrayObject, Object, TObject, Value};
use crate::string::AvmString; use crate::string::{AvmString, BorrowWStr, WStr};
use gc_arena::MutationContext; use gc_arena::MutationContext;
const PROTO_DECLS: &[Declaration] = declare_properties! { const PROTO_DECLS: &[Declaration] = declare_properties! {
@ -392,8 +392,8 @@ pub fn get_type<'gc>(
_args: &[Value<'gc>], _args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> { ) -> Result<Value<'gc>, Error<'gc>> {
if let Some(filter) = this.as_gradient_glow_filter_object() { if let Some(filter) = this.as_gradient_glow_filter_object() {
let type_: &str = filter.get_type().into(); let type_: WStr<'_> = filter.get_type().into();
return Ok(AvmString::new(activation.context.gc_context, type_.to_string()).into()); return Ok(AvmString::new_ucs2(activation.context.gc_context, type_.into()).into());
} }
Ok(Value::Undefined) Ok(Value::Undefined)
@ -408,7 +408,7 @@ pub fn set_type<'gc>(
.get(0) .get(0)
.unwrap_or(&"inner".into()) .unwrap_or(&"inner".into())
.coerce_to_string(activation) .coerce_to_string(activation)
.map(|s| s.as_str().into())?; .map(|s| s.borrow().into())?;
if let Some(filter) = this.as_gradient_glow_filter_object() { if let Some(filter) = this.as_gradient_glow_filter_object() {
filter.set_type(activation.context.gc_context, type_); filter.set_type(activation.context.gc_context, type_);

View File

@ -15,7 +15,7 @@ use crate::display_object::{
use crate::ecma_conversions::f64_to_wrapping_i32; use crate::ecma_conversions::f64_to_wrapping_i32;
use crate::prelude::*; use crate::prelude::*;
use crate::shape_utils::DrawCommand; use crate::shape_utils::DrawCommand;
use crate::string::AvmString; use crate::string::{AvmString, BorrowWStr};
use crate::vminterface::Instantiator; use crate::vminterface::Instantiator;
use gc_arena::MutationContext; use gc_arena::MutationContext;
use std::borrow::Cow; use std::borrow::Cow;
@ -262,28 +262,31 @@ fn line_style<'gc>(
let (allow_scale_x, allow_scale_y) = match args let (allow_scale_x, allow_scale_y) = match args
.get(4) .get(4)
.and_then(|v| v.coerce_to_string(activation).ok()) .and_then(|v| v.coerce_to_string(activation).ok())
.as_deref() .as_ref()
.map(|v| v.borrow())
{ {
Some("normal") => (true, true), Some(v) if v == b"normal" => (true, true),
Some("vertical") => (true, false), Some(v) if v == b"vertical" => (true, false),
Some("horizontal") => (false, true), Some(v) if v == b"horizontal" => (false, true),
_ => (false, false), _ => (false, false),
}; };
let cap_style = match args let cap_style = match args
.get(5) .get(5)
.and_then(|v| v.coerce_to_string(activation).ok()) .and_then(|v| v.coerce_to_string(activation).ok())
.as_deref() .as_ref()
.map(|v| v.borrow())
{ {
Some("square") => LineCapStyle::Square, Some(v) if v == b"square" => LineCapStyle::Square,
Some("none") => LineCapStyle::None, Some(v) if v == b"none" => LineCapStyle::None,
_ => LineCapStyle::Round, _ => LineCapStyle::Round,
}; };
let join_style = match args let join_style = match args
.get(6) .get(6)
.and_then(|v| v.coerce_to_string(activation).ok()) .and_then(|v| v.coerce_to_string(activation).ok())
.as_deref() .as_ref()
.map(|v| v.borrow())
{ {
Some("miter") => { Some(v) if v == b"miter" => {
if let Some(limit) = args.get(7) { if let Some(limit) = args.get(7) {
let limit = limit.coerce_to_f64(activation)?.clamp(0.0, 255.0); let limit = limit.coerce_to_f64(activation)?.clamp(0.0, 255.0);
LineJoinStyle::Miter(Fixed8::from_f64(limit)) LineJoinStyle::Miter(Fixed8::from_f64(limit))
@ -291,7 +294,7 @@ fn line_style<'gc>(
LineJoinStyle::Miter(Fixed8::from_f32(3.0)) LineJoinStyle::Miter(Fixed8::from_f32(3.0))
} }
} }
Some("bevel") => LineJoinStyle::Bevel, Some(v) if v == b"bevel" => LineJoinStyle::Bevel,
_ => LineJoinStyle::Round, _ => LineJoinStyle::Round,
}; };
movie_clip movie_clip
@ -468,18 +471,20 @@ fn begin_gradient_fill<'gc>(
let spread = match args let spread = match args
.get(5) .get(5)
.and_then(|v| v.coerce_to_string(activation).ok()) .and_then(|v| v.coerce_to_string(activation).ok())
.as_deref() .as_ref()
.map(|v| v.borrow())
{ {
Some("reflect") => GradientSpread::Reflect, Some(v) if v == b"reflect" => GradientSpread::Reflect,
Some("repeat") => GradientSpread::Repeat, Some(v) if v == b"repeat" => GradientSpread::Repeat,
_ => GradientSpread::Pad, _ => GradientSpread::Pad,
}; };
let interpolation = match args let interpolation = match args
.get(6) .get(6)
.and_then(|v| v.coerce_to_string(activation).ok()) .and_then(|v| v.coerce_to_string(activation).ok())
.as_deref() .as_ref()
.map(|v| v.borrow())
{ {
Some("linearRGB") => GradientInterpolation::LinearRgb, Some(v) if v == b"linearRGB" => GradientInterpolation::LinearRgb,
_ => GradientInterpolation::Rgb, _ => GradientInterpolation::Rgb,
}; };
@ -489,9 +494,9 @@ fn begin_gradient_fill<'gc>(
interpolation, interpolation,
records, records,
}; };
let style = match method.as_ref() { let style = if method == b"linear" {
"linear" => FillStyle::LinearGradient(gradient), FillStyle::LinearGradient(gradient)
"radial" => { } else if method == b"radial" {
if let Some(focal_point) = args.get(7) { if let Some(focal_point) = args.get(7) {
FillStyle::FocalGradient { FillStyle::FocalGradient {
gradient, gradient,
@ -500,15 +505,13 @@ fn begin_gradient_fill<'gc>(
} else { } else {
FillStyle::RadialGradient(gradient) FillStyle::RadialGradient(gradient)
} }
} } else {
other => {
avm_warn!( avm_warn!(
activation, activation,
"beginGradientFill() received invalid fill type {:?}", "beginGradientFill() received invalid fill type {:?}",
other method
); );
return Ok(Value::Undefined); return Ok(Value::Undefined);
}
}; };
movie_clip movie_clip
.as_drawing(activation.context.gc_context) .as_drawing(activation.context.gc_context)
@ -1004,7 +1007,7 @@ pub fn goto_frame<'gc>(
activation.resolve_variable_path(movie_clip.into(), &frame_path)? activation.resolve_variable_path(movie_clip.into(), &frame_path)?
{ {
if let Some(clip) = clip.as_display_object().and_then(|o| o.as_movie_clip()) { if let Some(clip) = clip.as_display_object().and_then(|o| o.as_movie_clip()) {
// TODO(moulins): we need Str::parse for avoiding allocation here. // TODO(moulins): we need WStr::parse for avoiding allocation here.
let frame = frame.to_string(); let frame = frame.to_string();
if let Ok(frame) = frame.parse().map(f64_to_wrapping_i32) { if let Ok(frame) = frame.parse().map(f64_to_wrapping_i32) {
// First try to parse as a frame number. // First try to parse as a frame number.

View File

@ -294,11 +294,14 @@ pub fn as_set_prop_flags<'gc>(
), ),
Some(v) => { Some(v) => {
let props = v.coerce_to_string(activation)?; let props = v.coerce_to_string(activation)?;
if props.as_str().contains(',') { if props.contains(b',') {
for prop_name in props.as_str().split(',') { for prop_name in props.split(b',') {
object.set_attributes( object.set_attributes(
activation.context.gc_context, activation.context.gc_context,
Some(AvmString::new(activation.context.gc_context, prop_name)), Some(AvmString::new_ucs2(
activation.context.gc_context,
prop_name.into(),
)),
set_attributes, set_attributes,
clear_attributes, clear_attributes,
) )

View File

@ -1,6 +1,7 @@
use crate::add_field_accessors; use crate::add_field_accessors;
use crate::avm1::{Object, ScriptObject, TObject}; use crate::avm1::{Object, ScriptObject, TObject};
use crate::impl_custom_object; use crate::impl_custom_object;
use crate::string::WStr;
use gc_arena::{Collect, GcCell, MutationContext}; use gc_arena::{Collect, GcCell, MutationContext};
use std::fmt; use std::fmt;
@ -13,24 +14,26 @@ pub enum BevelFilterType {
Full, Full,
} }
impl From<&str> for BevelFilterType { impl From<WStr<'_>> for BevelFilterType {
fn from(value: &str) -> Self { fn from(value: WStr<'_>) -> Self {
match value { if value == b"inner" {
"inner" => BevelFilterType::Inner, BevelFilterType::Inner
"outer" => BevelFilterType::Outer, } else if value == b"outer" {
"full" => BevelFilterType::Full, BevelFilterType::Outer
_ => BevelFilterType::Full, } else {
BevelFilterType::Full
} }
} }
} }
impl From<BevelFilterType> for &str { impl From<BevelFilterType> for WStr<'static> {
fn from(v: BevelFilterType) -> Self { fn from(v: BevelFilterType) -> WStr<'static> {
match v { let s: &[u8] = match v {
BevelFilterType::Inner => "inner", BevelFilterType::Inner => b"inner",
BevelFilterType::Outer => "outer", BevelFilterType::Outer => b"outer",
BevelFilterType::Full => "full", BevelFilterType::Full => b"full",
} };
WStr::from_units(s)
} }
} }

View File

@ -1,6 +1,7 @@
use crate::add_field_accessors; use crate::add_field_accessors;
use crate::avm1::{Object, ScriptObject, TObject}; use crate::avm1::{Object, ScriptObject, TObject};
use crate::impl_custom_object; use crate::impl_custom_object;
use crate::string::WStr;
use gc_arena::{Collect, GcCell, MutationContext}; use gc_arena::{Collect, GcCell, MutationContext};
use std::fmt; use std::fmt;
@ -14,32 +15,29 @@ pub enum DisplacementMapFilterMode {
Color, Color,
} }
impl From<&str> for DisplacementMapFilterMode { impl From<WStr<'_>> for DisplacementMapFilterMode {
fn from(v: &str) -> DisplacementMapFilterMode { fn from(v: WStr<'_>) -> DisplacementMapFilterMode {
match v { if v == b"clamp" {
"wrap" => DisplacementMapFilterMode::Wrap, DisplacementMapFilterMode::Clamp
"clamp" => DisplacementMapFilterMode::Clamp, } else if v == b"ignore" {
"ignore" => DisplacementMapFilterMode::Ignore, DisplacementMapFilterMode::Ignore
"color" => DisplacementMapFilterMode::Color, } else if v == b"color" {
_ => DisplacementMapFilterMode::Wrap, DisplacementMapFilterMode::Color
} else {
DisplacementMapFilterMode::Wrap
} }
} }
} }
impl From<DisplacementMapFilterMode> for &str { impl From<DisplacementMapFilterMode> for WStr<'static> {
fn from(v: DisplacementMapFilterMode) -> Self { fn from(v: DisplacementMapFilterMode) -> Self {
match v { let s: &[u8] = match v {
DisplacementMapFilterMode::Wrap => "wrap", DisplacementMapFilterMode::Wrap => b"wrap",
DisplacementMapFilterMode::Clamp => "clamp", DisplacementMapFilterMode::Clamp => b"clamp",
DisplacementMapFilterMode::Ignore => "ignore", DisplacementMapFilterMode::Ignore => b"ignore",
DisplacementMapFilterMode::Color => "color", DisplacementMapFilterMode::Color => b"color",
} };
} WStr::from_units(s)
}
impl From<DisplacementMapFilterMode> for String {
fn from(v: DisplacementMapFilterMode) -> Self {
Into::<&str>::into(v).to_string()
} }
} }