avm2: Move top-level functions and __ruffle__ stub functions to ActionScript
This commit is contained in:
parent
ff2814c84f
commit
4561fd3631
|
@ -1,8 +1,7 @@
|
|||
use crate::avm2::activation::Activation;
|
||||
use crate::avm2::class::Class;
|
||||
use crate::avm2::domain::Domain;
|
||||
use crate::avm2::method::{Method, NativeMethodImpl};
|
||||
use crate::avm2::object::{ClassObject, FunctionObject, Object, ScriptObject, TObject};
|
||||
use crate::avm2::object::{ClassObject, Object, ScriptObject, TObject};
|
||||
use crate::avm2::scope::{Scope, ScopeChain};
|
||||
use crate::avm2::script::Script;
|
||||
use crate::avm2::Avm2;
|
||||
|
@ -15,6 +14,7 @@ use gc_arena::{Collect, GcCell, Mutation};
|
|||
use std::sync::Arc;
|
||||
use swf::TagCode;
|
||||
|
||||
mod __ruffle__;
|
||||
mod array;
|
||||
mod avmplus;
|
||||
mod boolean;
|
||||
|
@ -40,6 +40,19 @@ mod void;
|
|||
mod xml;
|
||||
mod xml_list;
|
||||
|
||||
pub use toplevel::decode_uri;
|
||||
pub use toplevel::decode_uri_component;
|
||||
pub use toplevel::encode_uri;
|
||||
pub use toplevel::encode_uri_component;
|
||||
pub use toplevel::escape;
|
||||
pub use toplevel::is_finite;
|
||||
pub use toplevel::is_na_n;
|
||||
pub use toplevel::is_xml_name;
|
||||
pub use toplevel::parse_float;
|
||||
pub use toplevel::parse_int;
|
||||
pub use toplevel::trace;
|
||||
pub use toplevel::unescape;
|
||||
|
||||
/// This structure represents all system builtin classes.
|
||||
#[derive(Clone, Collect)]
|
||||
#[collect(no_drop)]
|
||||
|
@ -282,27 +295,30 @@ impl<'gc> SystemClasses<'gc> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Add a free-function builtin to the global scope.
|
||||
fn function<'gc>(
|
||||
/// Looks up a function defined in the script domain, and defines it on the global object.
|
||||
///
|
||||
/// This expects the looked-up value to be a function.
|
||||
fn define_fn_on_global<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
package: impl Into<AvmString<'gc>>,
|
||||
name: &'static str,
|
||||
nf: NativeMethodImpl,
|
||||
script: Script<'gc>,
|
||||
) -> Result<(), Error<'gc>> {
|
||||
let (_, global, mut domain) = script.init();
|
||||
let mc = activation.context.gc_context;
|
||||
let scope = activation.create_scopechain();
|
||||
) {
|
||||
let (_, global, domain) = script.init();
|
||||
let qname = QName::new(
|
||||
Namespace::package(package, &mut activation.borrow_gc()),
|
||||
name,
|
||||
);
|
||||
let method = Method::from_builtin(nf, name, mc);
|
||||
let as3fn = FunctionObject::from_method(activation, method, scope, None, None).into();
|
||||
domain.export_definition(qname, script, mc);
|
||||
global.install_const_late(mc, qname, as3fn, activation.avm2().classes().function);
|
||||
let func = domain
|
||||
.get_defined_value(activation, qname)
|
||||
.expect("Function being defined on global should be defined in domain!");
|
||||
|
||||
Ok(())
|
||||
global.install_const_late(
|
||||
activation.context.gc_context,
|
||||
qname,
|
||||
func,
|
||||
activation.avm2().classes().function,
|
||||
);
|
||||
}
|
||||
|
||||
/// Add a fully-formed class object builtin to the global scope.
|
||||
|
@ -561,66 +577,6 @@ pub fn load_player_globals<'gc>(
|
|||
// it should only be visible as an type for typecheck/cast purposes.
|
||||
avm2_system_class!(void, activation, void::create_class(activation), script);
|
||||
|
||||
function(activation, "", "trace", toplevel::trace, script)?;
|
||||
function(
|
||||
activation,
|
||||
"__ruffle__",
|
||||
"log_warn",
|
||||
toplevel::log_warn,
|
||||
script,
|
||||
)?;
|
||||
function(
|
||||
activation,
|
||||
"__ruffle__",
|
||||
"stub_method",
|
||||
toplevel::stub_method,
|
||||
script,
|
||||
)?;
|
||||
function(
|
||||
activation,
|
||||
"__ruffle__",
|
||||
"stub_getter",
|
||||
toplevel::stub_getter,
|
||||
script,
|
||||
)?;
|
||||
function(
|
||||
activation,
|
||||
"__ruffle__",
|
||||
"stub_setter",
|
||||
toplevel::stub_setter,
|
||||
script,
|
||||
)?;
|
||||
function(
|
||||
activation,
|
||||
"__ruffle__",
|
||||
"stub_constructor",
|
||||
toplevel::stub_constructor,
|
||||
script,
|
||||
)?;
|
||||
function(activation, "", "isFinite", toplevel::is_finite, script)?;
|
||||
function(activation, "", "isNaN", toplevel::is_nan, script)?;
|
||||
function(activation, "", "isXMLName", toplevel::is_xml_name, script)?;
|
||||
function(activation, "", "parseInt", toplevel::parse_int, script)?;
|
||||
function(activation, "", "parseFloat", toplevel::parse_float, script)?;
|
||||
function(activation, "", "escape", toplevel::escape, script)?;
|
||||
function(activation, "", "encodeURI", toplevel::encode_uri, script)?;
|
||||
function(
|
||||
activation,
|
||||
"",
|
||||
"encodeURIComponent",
|
||||
toplevel::encode_uri_component,
|
||||
script,
|
||||
)?;
|
||||
function(activation, "", "decodeURI", toplevel::decode_uri, script)?;
|
||||
function(
|
||||
activation,
|
||||
"",
|
||||
"decodeURIComponent",
|
||||
toplevel::decode_uri_component,
|
||||
script,
|
||||
)?;
|
||||
function(activation, "", "unescape", toplevel::unescape, script)?;
|
||||
|
||||
avm2_system_class!(
|
||||
generic_vector,
|
||||
activation,
|
||||
|
@ -658,10 +614,24 @@ pub fn load_player_globals<'gc>(
|
|||
|
||||
// Inside this call, the macro `avm2_system_classes_playerglobal`
|
||||
// triggers classloading. Therefore, we run `load_playerglobal`
|
||||
// relative late, so that it can access classes defined before
|
||||
// relatively late, so that it can access classes defined before
|
||||
// this call.
|
||||
load_playerglobal(activation, domain)?;
|
||||
|
||||
// Except for `trace`, top-level builtin functions are defined
|
||||
// on the `global` object.
|
||||
define_fn_on_global(activation, "", "decodeURI", script);
|
||||
define_fn_on_global(activation, "", "decodeURIComponent", script);
|
||||
define_fn_on_global(activation, "", "encodeURI", script);
|
||||
define_fn_on_global(activation, "", "encodeURIComponent", script);
|
||||
define_fn_on_global(activation, "", "escape", script);
|
||||
define_fn_on_global(activation, "", "unescape", script);
|
||||
define_fn_on_global(activation, "", "isXMLName", script);
|
||||
define_fn_on_global(activation, "", "isFinite", script);
|
||||
define_fn_on_global(activation, "", "isNaN", script);
|
||||
define_fn_on_global(activation, "", "parseFloat", script);
|
||||
define_fn_on_global(activation, "", "parseInt", script);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -6,4 +6,23 @@ package {
|
|||
public const Infinity: Number = 1 / 0;
|
||||
|
||||
public const undefined = void 0;
|
||||
|
||||
public native function encodeURI(uri:String = "undefined"):String;
|
||||
public native function encodeURIComponent(uri:String = "undefined"):String;
|
||||
|
||||
public native function decodeURI(uri:String = "undefined"):String;
|
||||
public native function decodeURIComponent(uri:String = "undefined"):String;
|
||||
|
||||
public native function escape(string:String = "undefined"):String;
|
||||
public native function unescape(string:String = "undefined"):String;
|
||||
|
||||
public native function isXMLName(string:* = undefined):Boolean;
|
||||
|
||||
public native function isFinite(value:Number = undefined):Boolean;
|
||||
public native function isNaN(value:Number = undefined):Boolean;
|
||||
|
||||
public native function parseFloat(number:String = "NaN"):Number;
|
||||
public native function parseInt(string:String = "NaN", base:int = 0):Number;
|
||||
|
||||
public native function trace(... rest):void;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
use crate::avm2::activation::Activation;
|
||||
use crate::avm2::error::Error;
|
||||
use crate::avm2::object::Object;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::stub::Stub;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub fn stub_method<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[class, method] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let method = method.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Method {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
method: Cow::Owned(method.to_utf8_lossy().to_string()),
|
||||
specifics: None,
|
||||
});
|
||||
}
|
||||
[class, method, specifics] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let method = method.coerce_to_string(activation)?;
|
||||
let specifics = specifics.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Method {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
method: Cow::Owned(method.to_utf8_lossy().to_string()),
|
||||
specifics: Some(Cow::Owned(specifics.to_utf8_lossy().to_string())),
|
||||
});
|
||||
}
|
||||
_ => tracing::warn!("(__ruffle__.stub_method called with wrong args)"),
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn stub_getter<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[class, property] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let property = property.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Getter {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
property: Cow::Owned(property.to_utf8_lossy().to_string()),
|
||||
});
|
||||
}
|
||||
_ => tracing::warn!("(__ruffle__.stub_getter called with wrong args)"),
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn stub_setter<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[class, property] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let property = property.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Setter {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
property: Cow::Owned(property.to_utf8_lossy().to_string()),
|
||||
});
|
||||
}
|
||||
_ => tracing::warn!("(__ruffle__.stub_setter called with wrong args)"),
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn stub_constructor<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[class] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Constructor {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
specifics: None,
|
||||
});
|
||||
}
|
||||
[class, specifics] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let specifics = specifics.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Constructor {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
specifics: Some(Cow::Owned(specifics.to_utf8_lossy().to_string())),
|
||||
});
|
||||
}
|
||||
_ => tracing::warn!("(__ruffle__.stub_constructor called with wrong args)"),
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
package __ruffle__ {
|
||||
public native function log_warn(...arguments);
|
||||
|
||||
public native function stub_method(class_name, method);
|
||||
|
||||
public native function stub_getter(class_name, method);
|
||||
|
||||
public native function stub_setter(class_name, method);
|
||||
|
||||
public native function stub_constructor(class_name, method);
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package __ruffle__ {
|
||||
public native function stub_method(... rest):void;
|
||||
|
||||
public native function stub_getter(... rest):void;
|
||||
|
||||
public native function stub_setter(... rest):void;
|
||||
|
||||
public native function stub_constructor(... rest):void;
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
// List is ordered alphabetically, except where superclasses/interfaces
|
||||
// need to come before subclasses and implementations.
|
||||
|
||||
include "__ruffle__/stubs.as"
|
||||
|
||||
include "Error.as"
|
||||
|
||||
include "ArgumentError.as"
|
||||
|
|
|
@ -16,4 +16,3 @@ include "String.as"
|
|||
include "int.as"
|
||||
include "uint.as"
|
||||
include "Vector.as"
|
||||
include "__ruffle__/logging.as"
|
|
@ -5,11 +5,10 @@ use ruffle_wstr::Units;
|
|||
use crate::avm2::activation::Activation;
|
||||
use crate::avm2::error::{uri_error, Error};
|
||||
use crate::avm2::object::Object;
|
||||
use crate::avm2::parameters::ParametersExt;
|
||||
use crate::avm2::value::Value;
|
||||
use crate::string::{AvmString, WStr, WString};
|
||||
use crate::stub::Stub;
|
||||
use ruffle_wstr::Integer;
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Write;
|
||||
|
||||
pub fn trace<'gc>(
|
||||
|
@ -36,168 +35,24 @@ pub fn trace<'gc>(
|
|||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn log_warn<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[] => tracing::warn!("(__ruffle__.log_warn called with no arg)"),
|
||||
[arg] => {
|
||||
let msg = arg.coerce_to_string(activation)?;
|
||||
tracing::warn!("{}", &msg.to_utf8_lossy());
|
||||
}
|
||||
args => {
|
||||
let strings = args
|
||||
.iter()
|
||||
.map(|a| a.coerce_to_string(activation))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let msg = crate::string::join(&strings, &WStr::from_units(b" "));
|
||||
tracing::warn!("{}", &msg.to_utf8_lossy());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn stub_method<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[class, method] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let method = method.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Method {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
method: Cow::Owned(method.to_utf8_lossy().to_string()),
|
||||
specifics: None,
|
||||
});
|
||||
}
|
||||
[class, method, specifics] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let method = method.coerce_to_string(activation)?;
|
||||
let specifics = specifics.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Method {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
method: Cow::Owned(method.to_utf8_lossy().to_string()),
|
||||
specifics: Some(Cow::Owned(specifics.to_utf8_lossy().to_string())),
|
||||
});
|
||||
}
|
||||
_ => tracing::warn!("(__ruffle__.stub_method called with wrong args)"),
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn stub_getter<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[class, property] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let property = property.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Getter {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
property: Cow::Owned(property.to_utf8_lossy().to_string()),
|
||||
});
|
||||
}
|
||||
_ => tracing::warn!("(__ruffle__.stub_getter called with wrong args)"),
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn stub_setter<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[class, property] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let property = property.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Setter {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
property: Cow::Owned(property.to_utf8_lossy().to_string()),
|
||||
});
|
||||
}
|
||||
_ => tracing::warn!("(__ruffle__.stub_setter called with wrong args)"),
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn stub_constructor<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
match args {
|
||||
[class] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Constructor {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
specifics: None,
|
||||
});
|
||||
}
|
||||
[class, specifics] => {
|
||||
let class = class.coerce_to_string(activation)?;
|
||||
let specifics = specifics.coerce_to_string(activation)?;
|
||||
activation
|
||||
.context
|
||||
.stub_tracker
|
||||
.encounter(&Stub::Avm2Constructor {
|
||||
class: Cow::Owned(class.to_utf8_lossy().to_string()),
|
||||
specifics: Some(Cow::Owned(specifics.to_utf8_lossy().to_string())),
|
||||
});
|
||||
}
|
||||
_ => tracing::warn!("(__ruffle__.stub_constructor called with wrong args)"),
|
||||
}
|
||||
|
||||
Ok(Value::Undefined)
|
||||
}
|
||||
|
||||
pub fn is_finite<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
if let Some(val) = args.get(0) {
|
||||
Ok(val.coerce_to_number(activation)?.is_finite().into())
|
||||
} else {
|
||||
Ok(false.into())
|
||||
}
|
||||
let val = args.get_f64(activation, 0)?;
|
||||
|
||||
Ok(val.is_finite().into())
|
||||
}
|
||||
|
||||
pub fn is_nan<'gc>(
|
||||
pub fn is_na_n<'gc>(
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
if let Some(val) = args.get(0) {
|
||||
Ok(val.coerce_to_number(activation)?.is_nan().into())
|
||||
} else {
|
||||
Ok(true.into())
|
||||
}
|
||||
let val = args.get_f64(activation, 0)?;
|
||||
|
||||
Ok(val.is_nan().into())
|
||||
}
|
||||
|
||||
pub fn parse_int<'gc>(
|
||||
|
@ -205,15 +60,8 @@ pub fn parse_int<'gc>(
|
|||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let string = match args.get(0).unwrap_or(&Value::Undefined) {
|
||||
Value::Undefined => "null".into(),
|
||||
value => value.coerce_to_string(activation)?,
|
||||
};
|
||||
|
||||
let radix = match args.get(1) {
|
||||
Some(value) => value.coerce_to_i32(activation)?,
|
||||
None => 0,
|
||||
};
|
||||
let string = args.get_string(activation, 0)?;
|
||||
let radix = args.get_i32(activation, 1)?;
|
||||
|
||||
let result = crate::avm2::value::string_to_int(&string, radix, false);
|
||||
Ok(result.into())
|
||||
|
@ -224,15 +72,14 @@ pub fn parse_float<'gc>(
|
|||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
if let Some(value) = args.get(0) {
|
||||
let string = value.coerce_to_string(activation)?;
|
||||
let swf_version = activation.context.swf.version();
|
||||
if let Some(result) = crate::avm2::value::string_to_f64(&string, swf_version, false) {
|
||||
return Ok(result.into());
|
||||
}
|
||||
}
|
||||
let string = args.get_string(activation, 0)?;
|
||||
let swf_version = activation.context.swf.version();
|
||||
|
||||
Ok(f64::NAN.into())
|
||||
if let Some(result) = crate::avm2::value::string_to_f64(&string, swf_version, false) {
|
||||
Ok(result.into())
|
||||
} else {
|
||||
Ok(f64::NAN.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_xml_name<'gc>(
|
||||
|
@ -240,7 +87,7 @@ pub fn is_xml_name<'gc>(
|
|||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let name = args.get(0).unwrap_or(&Value::Undefined);
|
||||
let name = args.get_value(0);
|
||||
if matches!(name, Value::Undefined | Value::Null) {
|
||||
return Ok(false.into());
|
||||
}
|
||||
|
@ -255,11 +102,7 @@ pub fn escape<'gc>(
|
|||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let value = match args.first() {
|
||||
None => return Ok("undefined".into()),
|
||||
Some(Value::Undefined) => return Ok("null".into()),
|
||||
Some(value) => value,
|
||||
};
|
||||
let value = args.get_string(activation, 0)?;
|
||||
|
||||
let mut output = WString::new();
|
||||
|
||||
|
@ -267,7 +110,7 @@ pub fn escape<'gc>(
|
|||
let not_converted =
|
||||
WStr::from_units(b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@-_.*+/");
|
||||
|
||||
for x in value.coerce_to_string(activation)?.iter() {
|
||||
for x in value.iter() {
|
||||
if not_converted.contains(x) {
|
||||
output.push(x);
|
||||
} else {
|
||||
|
@ -288,11 +131,7 @@ pub fn unescape<'gc>(
|
|||
_this: Object<'gc>,
|
||||
args: &[Value<'gc>],
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let value = match args.first() {
|
||||
None => return Ok("undefined".into()),
|
||||
Some(Value::Undefined) => return Ok("null".into()),
|
||||
Some(value) => value.coerce_to_string(activation)?,
|
||||
};
|
||||
let value = args.get_string(activation, 0)?;
|
||||
|
||||
let mut output = WString::new();
|
||||
let mut index = 0;
|
||||
|
@ -361,15 +200,9 @@ fn encode_utf8_with_exclusions<'gc>(
|
|||
args: &[Value<'gc>],
|
||||
not_converted: &str,
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let value = match args.first() {
|
||||
None => return Ok("undefined".into()),
|
||||
Some(Value::Undefined) => return Ok("null".into()),
|
||||
Some(value) => value,
|
||||
};
|
||||
|
||||
let input = args.get_string(activation, 0)?;
|
||||
let mut output = String::new();
|
||||
|
||||
let input = value.coerce_to_string(activation)?;
|
||||
let input_string = match input.units() {
|
||||
// Latin-1 values map directly to unicode codepoints,
|
||||
// so we can directly convert to a `char`
|
||||
|
@ -434,11 +267,7 @@ fn decode<'gc>(
|
|||
reserved_set: &str,
|
||||
func_name: &str,
|
||||
) -> Result<Value<'gc>, Error<'gc>> {
|
||||
let value = match args.first() {
|
||||
None => return Ok("undefined".into()),
|
||||
Some(Value::Undefined) => return Ok("null".into()),
|
||||
Some(value) => value.coerce_to_string(activation)?,
|
||||
};
|
||||
let value = args.get_string(activation, 0)?;
|
||||
|
||||
let mut output = WString::new();
|
||||
let mut chars = value.chars();
|
||||
|
|
Loading…
Reference in New Issue