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

View File

@ -6,7 +6,7 @@ use crate::avm1::object::bevel_filter::BevelFilterType;
use crate::avm1::object::gradient_bevel_filter::GradientBevelFilterObject;
use crate::avm1::property_decl::{define_properties_on, Declaration};
use crate::avm1::{ArrayObject, Object, TObject, Value};
use crate::string::AvmString;
use crate::string::{AvmString, BorrowWStr, WStr};
use gc_arena::MutationContext;
const PROTO_DECLS: &[Declaration] = declare_properties! {
@ -392,8 +392,8 @@ pub fn get_type<'gc>(
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(filter) = this.as_gradient_bevel_filter_object() {
let type_: &str = filter.get_type().into();
return Ok(AvmString::new(activation.context.gc_context, type_.to_string()).into());
let type_: WStr<'_> = filter.get_type().into();
return Ok(AvmString::new_ucs2(activation.context.gc_context, type_.into()).into());
}
Ok(Value::Undefined)
@ -408,7 +408,7 @@ pub fn set_type<'gc>(
.get(0)
.unwrap_or(&"inner".into())
.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() {
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::property_decl::{define_properties_on, Declaration};
use crate::avm1::{ArrayObject, Object, TObject, Value};
use crate::string::AvmString;
use crate::string::{AvmString, BorrowWStr, WStr};
use gc_arena::MutationContext;
const PROTO_DECLS: &[Declaration] = declare_properties! {
@ -392,8 +392,8 @@ pub fn get_type<'gc>(
_args: &[Value<'gc>],
) -> Result<Value<'gc>, Error<'gc>> {
if let Some(filter) = this.as_gradient_glow_filter_object() {
let type_: &str = filter.get_type().into();
return Ok(AvmString::new(activation.context.gc_context, type_.to_string()).into());
let type_: WStr<'_> = filter.get_type().into();
return Ok(AvmString::new_ucs2(activation.context.gc_context, type_.into()).into());
}
Ok(Value::Undefined)
@ -408,7 +408,7 @@ pub fn set_type<'gc>(
.get(0)
.unwrap_or(&"inner".into())
.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() {
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::prelude::*;
use crate::shape_utils::DrawCommand;
use crate::string::AvmString;
use crate::string::{AvmString, BorrowWStr};
use crate::vminterface::Instantiator;
use gc_arena::MutationContext;
use std::borrow::Cow;
@ -262,28 +262,31 @@ fn line_style<'gc>(
let (allow_scale_x, allow_scale_y) = match args
.get(4)
.and_then(|v| v.coerce_to_string(activation).ok())
.as_deref()
.as_ref()
.map(|v| v.borrow())
{
Some("normal") => (true, true),
Some("vertical") => (true, false),
Some("horizontal") => (false, true),
Some(v) if v == b"normal" => (true, true),
Some(v) if v == b"vertical" => (true, false),
Some(v) if v == b"horizontal" => (false, true),
_ => (false, false),
};
let cap_style = match args
.get(5)
.and_then(|v| v.coerce_to_string(activation).ok())
.as_deref()
.as_ref()
.map(|v| v.borrow())
{
Some("square") => LineCapStyle::Square,
Some("none") => LineCapStyle::None,
Some(v) if v == b"square" => LineCapStyle::Square,
Some(v) if v == b"none" => LineCapStyle::None,
_ => LineCapStyle::Round,
};
let join_style = match args
.get(6)
.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) {
let limit = limit.coerce_to_f64(activation)?.clamp(0.0, 255.0);
LineJoinStyle::Miter(Fixed8::from_f64(limit))
@ -291,7 +294,7 @@ fn line_style<'gc>(
LineJoinStyle::Miter(Fixed8::from_f32(3.0))
}
}
Some("bevel") => LineJoinStyle::Bevel,
Some(v) if v == b"bevel" => LineJoinStyle::Bevel,
_ => LineJoinStyle::Round,
};
movie_clip
@ -468,18 +471,20 @@ fn begin_gradient_fill<'gc>(
let spread = match args
.get(5)
.and_then(|v| v.coerce_to_string(activation).ok())
.as_deref()
.as_ref()
.map(|v| v.borrow())
{
Some("reflect") => GradientSpread::Reflect,
Some("repeat") => GradientSpread::Repeat,
Some(v) if v == b"reflect" => GradientSpread::Reflect,
Some(v) if v == b"repeat" => GradientSpread::Repeat,
_ => GradientSpread::Pad,
};
let interpolation = match args
.get(6)
.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,
};
@ -489,9 +494,9 @@ fn begin_gradient_fill<'gc>(
interpolation,
records,
};
let style = match method.as_ref() {
"linear" => FillStyle::LinearGradient(gradient),
"radial" => {
let style = if method == b"linear" {
FillStyle::LinearGradient(gradient)
} else if method == b"radial" {
if let Some(focal_point) = args.get(7) {
FillStyle::FocalGradient {
gradient,
@ -500,15 +505,13 @@ fn begin_gradient_fill<'gc>(
} else {
FillStyle::RadialGradient(gradient)
}
}
other => {
} else {
avm_warn!(
activation,
"beginGradientFill() received invalid fill type {:?}",
other
method
);
return Ok(Value::Undefined);
}
};
movie_clip
.as_drawing(activation.context.gc_context)
@ -1004,7 +1007,7 @@ pub fn goto_frame<'gc>(
activation.resolve_variable_path(movie_clip.into(), &frame_path)?
{
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();
if let Ok(frame) = frame.parse().map(f64_to_wrapping_i32) {
// First try to parse as a frame number.

View File

@ -294,11 +294,14 @@ pub fn as_set_prop_flags<'gc>(
),
Some(v) => {
let props = v.coerce_to_string(activation)?;
if props.as_str().contains(',') {
for prop_name in props.as_str().split(',') {
if props.contains(b',') {
for prop_name in props.split(b',') {
object.set_attributes(
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,
clear_attributes,
)

View File

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

View File

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