avm2: Implement encodeURI and encodeURIComponent
This commit is contained in:
parent
e970174339
commit
7f58b92348
|
@ -468,6 +468,14 @@ pub fn load_player_globals<'gc>(
|
||||||
function(activation, "", "parseInt", toplevel::parse_int, script)?;
|
function(activation, "", "parseInt", toplevel::parse_int, script)?;
|
||||||
function(activation, "", "parseFloat", toplevel::parse_float, script)?;
|
function(activation, "", "parseFloat", toplevel::parse_float, script)?;
|
||||||
function(activation, "", "escape", toplevel::escape, script)?;
|
function(activation, "", "escape", toplevel::escape, script)?;
|
||||||
|
function(activation, "", "encodeURI", toplevel::encode_uri, script)?;
|
||||||
|
function(
|
||||||
|
activation,
|
||||||
|
"",
|
||||||
|
"encodeURIComponent",
|
||||||
|
toplevel::encode_uri_component,
|
||||||
|
script,
|
||||||
|
)?;
|
||||||
|
|
||||||
avm2_system_class!(regexp, activation, regexp::create_class(activation), script);
|
avm2_system_class!(regexp, activation, regexp::create_class(activation), script);
|
||||||
avm2_system_class!(vector, activation, vector::create_class(activation), script);
|
avm2_system_class!(vector, activation, vector::create_class(activation), script);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
//! Global scope built-ins
|
//! Global scope built-ins
|
||||||
|
|
||||||
|
use ruffle_wstr::Units;
|
||||||
|
|
||||||
use crate::avm2::activation::Activation;
|
use crate::avm2::activation::Activation;
|
||||||
use crate::avm2::object::Object;
|
use crate::avm2::object::Object;
|
||||||
use crate::avm2::value::Value;
|
use crate::avm2::value::Value;
|
||||||
|
@ -7,6 +9,7 @@ use crate::avm2::Error;
|
||||||
use crate::string::{AvmString, WStr, WString};
|
use crate::string::{AvmString, WStr, WString};
|
||||||
use crate::stub::Stub;
|
use crate::stub::Stub;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
pub fn trace<'gc>(
|
pub fn trace<'gc>(
|
||||||
activation: &mut Activation<'_, 'gc>,
|
activation: &mut Activation<'_, 'gc>,
|
||||||
|
@ -263,3 +266,68 @@ pub fn escape<'gc>(
|
||||||
|
|
||||||
Ok(AvmString::new(activation.context.gc_context, output).into())
|
Ok(AvmString::new(activation.context.gc_context, output).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn encode_uri<'gc>(
|
||||||
|
activation: &mut Activation<'_, 'gc>,
|
||||||
|
_this: Option<Object<'gc>>,
|
||||||
|
args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
|
encode_utf8_with_exclusions(
|
||||||
|
activation,
|
||||||
|
args,
|
||||||
|
// Characters that are not escaped, sourced from as3 docs
|
||||||
|
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@;/?:@&=+$,#-_.!~*'()",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encode_uri_component<'gc>(
|
||||||
|
activation: &mut Activation<'_, 'gc>,
|
||||||
|
_this: Option<Object<'gc>>,
|
||||||
|
args: &[Value<'gc>],
|
||||||
|
) -> Result<Value<'gc>, Error<'gc>> {
|
||||||
|
encode_utf8_with_exclusions(
|
||||||
|
activation,
|
||||||
|
args,
|
||||||
|
// Characters that are not escaped, sourced from as3 docs
|
||||||
|
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.!~*'()",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_utf8_with_exclusions<'gc>(
|
||||||
|
activation: &mut Activation<'_, '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 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`
|
||||||
|
Units::Bytes(bytes) => bytes.iter().map(|b| *b as char).collect(),
|
||||||
|
Units::Wide(wide) => String::from_utf16_lossy(wide),
|
||||||
|
};
|
||||||
|
|
||||||
|
for x in input_string.chars() {
|
||||||
|
if not_converted.contains(x) {
|
||||||
|
output.push(x);
|
||||||
|
} else {
|
||||||
|
let mut bytes = [0; 4];
|
||||||
|
let utf8_bytes = x.encode_utf8(&mut bytes);
|
||||||
|
let mut encoded = String::new();
|
||||||
|
// Each byte in the utf-8 encoding is encoded as a hex value
|
||||||
|
for byte in utf8_bytes.bytes() {
|
||||||
|
write!(encoded, "%{x:02X}", x = byte).unwrap();
|
||||||
|
}
|
||||||
|
output.push_str(&encoded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(AvmString::new_utf8(activation.context.gc_context, output).into())
|
||||||
|
}
|
||||||
|
|
|
@ -4,38 +4,44 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace("// escape()");
|
import flash.utils.getDefinitionByName;
|
||||||
trace(escape());
|
|
||||||
trace("");
|
|
||||||
|
|
||||||
trace("// escape(undefined)");
|
var fns = ["escape", "encodeURI", "encodeURIComponent"];
|
||||||
trace(escape(undefined));
|
for each (var fnName in fns) {
|
||||||
trace("");
|
var fn = getDefinitionByName(fnName);
|
||||||
|
trace("// " + fnName + "()");
|
||||||
|
trace(fn());
|
||||||
|
trace("");
|
||||||
|
|
||||||
trace("// typeof(escape(undefined))");
|
trace("// " + fnName + "(undefined)");
|
||||||
trace(typeof(escape(undefined)));
|
trace(fn(undefined));
|
||||||
trace("");
|
trace("");
|
||||||
|
|
||||||
trace("// escape(null)");
|
trace("// typeof(" + fnName + "(undefined))");
|
||||||
trace(escape(null));
|
trace(typeof(fn(undefined)));
|
||||||
trace("");
|
trace("");
|
||||||
|
|
||||||
var input = "test";
|
trace("// " + fnName + "(null)");
|
||||||
trace("// escape(\"" + input + "\")");
|
trace(fn(null));
|
||||||
trace(escape(input));
|
trace("");
|
||||||
trace("");
|
|
||||||
|
|
||||||
var input = "!\"£$%^&*()1234567890qwertyuiop[]asdfghjkl;'#\zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:@~|ZXCVBNM<>?\u0010";
|
var input = "test";
|
||||||
trace("// escape(\"" + input + "\")");
|
trace("// " + fnName + "(\"" + input + "\")");
|
||||||
trace(escape(input));
|
trace(fn(input));
|
||||||
trace("");
|
trace("");
|
||||||
|
|
||||||
var input = "\x05";
|
var input = "!\"£$%^&*()1234567890qwertyuiop[]asdfghjkl;'#\zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:@~|ZXCVBNM<>?\u0010";
|
||||||
trace("// escape(\"\\x05\")");
|
trace("// " + fnName + "(\"" + input + "\")");
|
||||||
trace(escape(input));
|
trace(fn(input));
|
||||||
trace("");
|
trace("");
|
||||||
|
|
||||||
var input = "😭";
|
var input = "\x05";
|
||||||
trace("// escape(\"" + input + "\")");
|
trace("// " + fnName + "(\"\\x05\")");
|
||||||
trace(escape(input));
|
trace(fn(input));
|
||||||
trace("");
|
trace("");
|
||||||
|
|
||||||
|
var input = "😭";
|
||||||
|
trace("// " + fnName + "(\"" + input + "\")");
|
||||||
|
trace(fn(input));
|
||||||
|
trace("");
|
||||||
|
}
|
||||||
|
|
|
@ -22,3 +22,51 @@ test
|
||||||
// escape("😭")
|
// escape("😭")
|
||||||
%uD83D%uDE2D
|
%uD83D%uDE2D
|
||||||
|
|
||||||
|
// encodeURI()
|
||||||
|
undefined
|
||||||
|
|
||||||
|
// encodeURI(undefined)
|
||||||
|
null
|
||||||
|
|
||||||
|
// typeof(encodeURI(undefined))
|
||||||
|
string
|
||||||
|
|
||||||
|
// encodeURI(null)
|
||||||
|
null
|
||||||
|
|
||||||
|
// encodeURI("test")
|
||||||
|
test
|
||||||
|
|
||||||
|
// encodeURI("!"£$%^&*()1234567890qwertyuiop[]asdfghjkl;'#zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:@~|ZXCVBNM<>?")
|
||||||
|
!%22%C2%A3$%25%5E&*()1234567890qwertyuiop%5B%5Dasdfghjkl;'#zxcvbnm,./QWERTYUIOP%7B%7DASDFGHJKL:@~%7CZXCVBNM%3C%3E?%10
|
||||||
|
|
||||||
|
// encodeURI("\x05")
|
||||||
|
%05
|
||||||
|
|
||||||
|
// encodeURI("😭")
|
||||||
|
%F0%9F%98%AD
|
||||||
|
|
||||||
|
// encodeURIComponent()
|
||||||
|
undefined
|
||||||
|
|
||||||
|
// encodeURIComponent(undefined)
|
||||||
|
null
|
||||||
|
|
||||||
|
// typeof(encodeURIComponent(undefined))
|
||||||
|
string
|
||||||
|
|
||||||
|
// encodeURIComponent(null)
|
||||||
|
null
|
||||||
|
|
||||||
|
// encodeURIComponent("test")
|
||||||
|
test
|
||||||
|
|
||||||
|
// encodeURIComponent("!"£$%^&*()1234567890qwertyuiop[]asdfghjkl;'#zxcvbnm,./QWERTYUIOP{}ASDFGHJKL:@~|ZXCVBNM<>?")
|
||||||
|
!%22%C2%A3%24%25%5E%26*()1234567890qwertyuiop%5B%5Dasdfghjkl%3B'%23zxcvbnm%2C.%2FQWERTYUIOP%7B%7DASDFGHJKL%3A%40~%7CZXCVBNM%3C%3E%3F%10
|
||||||
|
|
||||||
|
// encodeURIComponent("\x05")
|
||||||
|
%05
|
||||||
|
|
||||||
|
// encodeURIComponent("😭")
|
||||||
|
%F0%9F%98%AD
|
||||||
|
|
||||||
|
|
Binary file not shown.
Loading…
Reference in New Issue