mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-27 04:01:11 +08:00
fix: 排序默认比较改 UTF-16 码元序
This commit is contained in:
Generated
+18
-18
@@ -1095,7 +1095,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_builtins"
|
name = "oxide_builtins"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"fast-float",
|
"fast-float",
|
||||||
@@ -1120,7 +1120,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_bytecode"
|
name = "oxide_bytecode"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1128,7 +1128,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cfg"
|
name = "oxide_cfg"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_emit",
|
"oxide_emit",
|
||||||
@@ -1139,7 +1139,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_cli"
|
name = "oxide_cli"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ansi_term",
|
"ansi_term",
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
@@ -1159,7 +1159,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_code_cache"
|
name = "oxide_code_cache"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lru",
|
"lru",
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
@@ -1168,7 +1168,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_compiler"
|
name = "oxide_compiler"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1187,7 +1187,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_dce"
|
name = "oxide_dce"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1201,7 +1201,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_emit"
|
name = "oxide_emit"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
@@ -1216,7 +1216,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_ir"
|
name = "oxide_ir"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_log",
|
"oxide_log",
|
||||||
@@ -1225,7 +1225,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_kernel"
|
name = "oxide_kernel"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"dashmap",
|
"dashmap",
|
||||||
@@ -1240,7 +1240,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_liveness"
|
name = "oxide_liveness"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1252,7 +1252,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_log"
|
name = "oxide_log"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-appender",
|
"tracing-appender",
|
||||||
@@ -1261,7 +1261,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_parser"
|
name = "oxide_parser"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxc_allocator",
|
"oxc_allocator",
|
||||||
"oxc_ast",
|
"oxc_ast",
|
||||||
@@ -1276,7 +1276,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_regalloc"
|
name = "oxide_regalloc"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_cfg",
|
"oxide_cfg",
|
||||||
@@ -1292,7 +1292,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_runtime_api"
|
name = "oxide_runtime_api"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
@@ -1304,7 +1304,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_test262"
|
name = "oxide_test262"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxide_bytecode",
|
"oxide_bytecode",
|
||||||
"oxide_compiler",
|
"oxide_compiler",
|
||||||
@@ -1321,7 +1321,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_types"
|
name = "oxide_types"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"hashbrown 0.14.5",
|
"hashbrown 0.14.5",
|
||||||
@@ -1333,7 +1333,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxide_vm"
|
name = "oxide_vm"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
rust-version = "1.80"
|
rust-version = "1.80"
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ pub fn array_with<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
|||||||
/// # 边界与前提
|
/// # 边界与前提
|
||||||
/// - 先校验 compareFn 可调用(非 undefined 且不可调用则抛 TypeError),再读取
|
/// - 先校验 compareFn 可调用(非 undefined 且不可调用则抛 TypeError),再读取
|
||||||
/// this/length;
|
/// this/length;
|
||||||
/// - 未提供比较回调时按 ToString 结果的字符串字典序排序;底层 `sort_by` 为稳定
|
/// - 未提供比较回调时按 ToString 结果的 UTF-16 码元字典序排序;底层 `sort_by` 为稳定
|
||||||
/// 排序,比较结果相等的元素保持原有相对次序。
|
/// 排序,比较结果相等的元素保持原有相对次序。
|
||||||
pub fn array_to_sorted<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
pub fn array_to_sorted<H: VmHost>(vm: &mut H, args: &[u8]) -> NativeResult {
|
||||||
builtins_debug!("Array.prototype.toSorted called with {} args", args.len());
|
builtins_debug!("Array.prototype.toSorted called with {} args", args.len());
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ use super::common::{
|
|||||||
|
|
||||||
/// 对元素向量执行 `Array.prototype.sort` 的比较语义(原地排序)。
|
/// 对元素向量执行 `Array.prototype.sort` 的比较语义(原地排序)。
|
||||||
///
|
///
|
||||||
/// 默认按 ToString 结果的字符串字典序比较;提供比较回调时按其返回值
|
/// 默认按 ToString 结果的 UTF-16 码元字典序比较;提供比较回调时按其返回值
|
||||||
///(<0/=0/>0)决定次序,回调抛错则中止并把异常原样返回。
|
///(<0/=0/>0)决定次序,回调抛错则中止并把异常原样返回。
|
||||||
pub(crate) fn sort_values_inner<H: VmHost>(
|
pub(crate) fn sort_values_inner<H: VmHost>(
|
||||||
vm: &mut H, vals: &mut [JsValue], comparator: Option<JsValue>,
|
vm: &mut H, vals: &mut [JsValue], comparator: Option<JsValue>,
|
||||||
@@ -48,9 +48,12 @@ pub(crate) fn sort_values_inner<H: VmHost>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// 规范 CompareArrayElements 对 ToString 结果做关系比较,字符串按
|
||||||
|
// UTF-16 码元字典序;码元序列比较与码点序在补充平面字符处分歧,
|
||||||
|
// 此处以码元序为准。
|
||||||
let sa = oxide_runtime_api::to_string(*a);
|
let sa = oxide_runtime_api::to_string(*a);
|
||||||
let sb = oxide_runtime_api::to_string(*b);
|
let sb = oxide_runtime_api::to_string(*b);
|
||||||
sa.cmp(&sb)
|
sa.encode_utf16().cmp(sb.encode_utf16())
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if let Some(err) = sort_error {
|
if let Some(err) = sort_error {
|
||||||
@@ -72,7 +75,7 @@ pub(crate) fn parse_sort_comparator<H: VmHost>(vm: &mut H, candidate: JsValue) -
|
|||||||
|
|
||||||
/// 原地排序数组元素并返回原数组(`Array.prototype.sort`)。
|
/// 原地排序数组元素并返回原数组(`Array.prototype.sort`)。
|
||||||
///
|
///
|
||||||
/// 未提供比较回调时按 ToString 结果的字符串字典序排序;底层 `sort_by` 为稳定
|
/// 未提供比较回调时按 ToString 结果的 UTF-16 码元字典序排序;底层 `sort_by` 为稳定
|
||||||
/// 排序,比较结果相等(含 NaN)的元素保持原有相对次序。洞位不参与比较:
|
/// 排序,比较结果相等(含 NaN)的元素保持原有相对次序。洞位不参与比较:
|
||||||
/// present 值稳定排序后自索引 0 紧凑写回,尾部空位转为洞。
|
/// present 值稳定排序后自索引 0 紧凑写回,尾部空位转为洞。
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -351,6 +351,24 @@ fn array_sort_propagates_comparator_exception() {
|
|||||||
assert_eq!(to_str(&vm, result), "cmp");
|
assert_eq!(to_str(&vm, result), "cmp");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn array_sort_default_orders_by_utf16_code_units() {
|
||||||
|
// 默认排序按 UTF-16 码元字典序(规范 CompareArrayElements):补充平面字符
|
||||||
|
// 以高代理(U+D800 及以上)参与比较,小于 U+E000..U+FFFF,与码点序分歧。
|
||||||
|
// 前三例为判别例(码点序下结果相反),后两例为边界钉(两口径一致)。
|
||||||
|
let cases = [
|
||||||
|
("['\\u{10000}','\\uFFFF'].sort().join('')", "\u{10000}\u{FFFF}"),
|
||||||
|
("['\\uFFFF','\\u{10000}'].toSorted().join('')", "\u{10000}\u{FFFF}"),
|
||||||
|
("['\\u{10000}','A','\\uFFFF'].sort().join('')", "A\u{10000}\u{FFFF}"),
|
||||||
|
("['\\uD7FF','\\u{10000}'].sort().join('')", "\u{D7FF}\u{10000}"),
|
||||||
|
("['\\u{12345}','\\u{10000}'].sort().join('')", "\u{10000}\u{12345}"),
|
||||||
|
];
|
||||||
|
for (source, expected) in cases {
|
||||||
|
let (vm, result) = eval(source).unwrap();
|
||||||
|
assert_eq!(to_str(&vm, result), expected, "source: {source}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn array_callback_type_errors_are_not_sentinels() {
|
fn array_callback_type_errors_are_not_sentinels() {
|
||||||
let (vm, result) = eval("try { [1].map(null) } catch (e) { e.name }").unwrap();
|
let (vm, result) = eval("try { [1].map(null) } catch (e) { e.name }").unwrap();
|
||||||
|
|||||||
Reference in New Issue
Block a user