mirror of
https://github.com/lexmount/moli.git
synced 2026-11-04 08:07:27 +00:00
fix(geometry): convert matrix dictionary ancestors first
This commit is contained in:
@@ -555,28 +555,18 @@ impl Default for DomPointInit {
|
||||
#[derive(Default, webidl::WebIdlDictionary)]
|
||||
#[webidl(prefix = "DOMMatrixInit")]
|
||||
struct DomMatrixInit {
|
||||
a: Option<f64>,
|
||||
b: Option<f64>,
|
||||
c: Option<f64>,
|
||||
d: Option<f64>,
|
||||
e: Option<f64>,
|
||||
f: Option<f64>,
|
||||
#[webidl(inherit)]
|
||||
base: DomMatrix2DInit,
|
||||
#[webidl(name = "is2D")]
|
||||
is_2d: Option<bool>,
|
||||
m11: Option<f64>,
|
||||
m12: Option<f64>,
|
||||
m13: Option<f64>,
|
||||
m14: Option<f64>,
|
||||
m21: Option<f64>,
|
||||
m22: Option<f64>,
|
||||
m23: Option<f64>,
|
||||
m24: Option<f64>,
|
||||
m31: Option<f64>,
|
||||
m32: Option<f64>,
|
||||
m33: Option<f64>,
|
||||
m34: Option<f64>,
|
||||
m41: Option<f64>,
|
||||
m42: Option<f64>,
|
||||
m43: Option<f64>,
|
||||
m44: Option<f64>,
|
||||
}
|
||||
@@ -1222,18 +1212,60 @@ fn validated_dom_matrix_init(
|
||||
scope: &mut v8::PinScope<'_, '_>,
|
||||
init: DomMatrixInit,
|
||||
) -> Option<DomMatrixValue> {
|
||||
let m11 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "a", init.a, "m11", init.m11, 1.0)?;
|
||||
let m12 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "b", init.b, "m12", init.m12, 0.0)?;
|
||||
let m21 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "c", init.c, "m21", init.m21, 0.0)?;
|
||||
let m22 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "d", init.d, "m22", init.m22, 1.0)?;
|
||||
let m41 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "e", init.e, "m41", init.m41, 0.0)?;
|
||||
let m42 =
|
||||
validated_dom_matrix_alias(scope, "DOMMatrixInit", "f", init.f, "m42", init.m42, 0.0)?;
|
||||
let m11 = validated_dom_matrix_alias(
|
||||
scope,
|
||||
"DOMMatrixInit",
|
||||
"a",
|
||||
init.base.a,
|
||||
"m11",
|
||||
init.base.m11,
|
||||
1.0,
|
||||
)?;
|
||||
let m12 = validated_dom_matrix_alias(
|
||||
scope,
|
||||
"DOMMatrixInit",
|
||||
"b",
|
||||
init.base.b,
|
||||
"m12",
|
||||
init.base.m12,
|
||||
0.0,
|
||||
)?;
|
||||
let m21 = validated_dom_matrix_alias(
|
||||
scope,
|
||||
"DOMMatrixInit",
|
||||
"c",
|
||||
init.base.c,
|
||||
"m21",
|
||||
init.base.m21,
|
||||
0.0,
|
||||
)?;
|
||||
let m22 = validated_dom_matrix_alias(
|
||||
scope,
|
||||
"DOMMatrixInit",
|
||||
"d",
|
||||
init.base.d,
|
||||
"m22",
|
||||
init.base.m22,
|
||||
1.0,
|
||||
)?;
|
||||
let m41 = validated_dom_matrix_alias(
|
||||
scope,
|
||||
"DOMMatrixInit",
|
||||
"e",
|
||||
init.base.e,
|
||||
"m41",
|
||||
init.base.m41,
|
||||
0.0,
|
||||
)?;
|
||||
let m42 = validated_dom_matrix_alias(
|
||||
scope,
|
||||
"DOMMatrixInit",
|
||||
"f",
|
||||
init.base.f,
|
||||
"m42",
|
||||
init.base.m42,
|
||||
0.0,
|
||||
)?;
|
||||
let components = DomMatrixComponents {
|
||||
m11,
|
||||
m12,
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
(() => {
|
||||
const checks = [];
|
||||
const check = (name, fn) => {
|
||||
try { checks.push({name, passed: fn() === true}); }
|
||||
catch (error) { checks.push({name, passed: false, error: String(error)}); }
|
||||
};
|
||||
const realms = [window, document.querySelector('iframe').contentWindow];
|
||||
const base = ['a', 'b', 'c', 'd', 'e', 'f', 'm11', 'm12', 'm21', 'm22', 'm41', 'm42'];
|
||||
const own = ['is2D', 'm13', 'm14', 'm23', 'm24', 'm31', 'm32', 'm33', 'm34', 'm43', 'm44'];
|
||||
const names = [...base, ...own];
|
||||
for (const [ownerIndex, owner] of realms.entries()) {
|
||||
for (const [calleeIndex, callee] of realms.entries()) {
|
||||
const calls = [
|
||||
['DOMMatrix.fromMatrix', value => callee.DOMMatrix.fromMatrix(value)],
|
||||
['DOMMatrixReadOnly.fromMatrix', value => callee.DOMMatrixReadOnly.fromMatrix(value)],
|
||||
['DOMPoint.matrixTransform', value => new callee.DOMPoint(1, 2, 3, 1).matrixTransform(value)],
|
||||
['DOMMatrix.multiply', value => new callee.DOMMatrix().multiply(value)],
|
||||
['DOMMatrix.multiplySelf', value => new callee.DOMMatrix().multiplySelf(value)],
|
||||
['DOMMatrix.preMultiplySelf', value => new callee.DOMMatrix().preMultiplySelf(value)],
|
||||
];
|
||||
for (const [name, call] of calls) {
|
||||
const prefix = `matrix-order/${ownerIndex}/${calleeIndex}/${name}`;
|
||||
check(prefix + '/getter-conversion-order', () => {
|
||||
const order = [], value = {};
|
||||
for (const key of names) Object.defineProperty(value, key, {get() {
|
||||
order.push(key);
|
||||
return key === 'is2D' ? false : {valueOf() {order.push(key + ':number'); return 1;}};
|
||||
}});
|
||||
call(value);
|
||||
const expected = names.flatMap(key => key === 'is2D' ? [key] : [key, key + ':number']);
|
||||
return order.join() === expected.join();
|
||||
});
|
||||
for (const proxy of [false, true]) check(prefix + '/inherited-or-proxy/' + proxy, () => {
|
||||
const order = [], target = {};
|
||||
for (const key of names) Object.defineProperty(target, key, {get() {order.push(key); return key === 'is2D' ? false : 1;}});
|
||||
call(proxy ? new owner.Proxy(target, {}) : owner.Object.create(target));
|
||||
return order.join() === names.join();
|
||||
});
|
||||
for (const key of names) for (const conversion of [false, true]) {
|
||||
if (conversion && key === 'is2D') continue;
|
||||
check(prefix + '/exception/' + key + '/' + conversion, () => {
|
||||
const sentinel = {}, order = [], value = {};
|
||||
for (const member of names) Object.defineProperty(value, member, {get() {
|
||||
order.push(member);
|
||||
if (member === key) {
|
||||
if (!conversion) throw sentinel;
|
||||
return {valueOf() {order.push(member + ':number'); throw sentinel;}};
|
||||
}
|
||||
return member === 'is2D' ? false : 1;
|
||||
}});
|
||||
try { call(value); } catch (error) {
|
||||
const expected = names.slice(0, names.indexOf(key) + 1);
|
||||
if (conversion) expected.push(key + ':number');
|
||||
return error === sentinel && order.join() === expected.join();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
for (const [index, value] of [undefined, null, {}, [], () => {}].entries()) {
|
||||
check(prefix + '/empty/' + index, () => {call(value); return true;});
|
||||
}
|
||||
for (const [index, value] of [0, true, 'matrix', Symbol(), 1n].entries()) {
|
||||
check(prefix + '/invalid/' + index, () => {
|
||||
try {call(value);} catch (error) {return Object.getPrototypeOf(error) === callee.TypeError.prototype;}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
check(prefix + '/validation-after-all-members', () => {
|
||||
const order = [], sentinel = {};
|
||||
const value = new owner.Proxy({a: 1, m11: 2}, {get(target, key) {
|
||||
order.push(key);
|
||||
if (key === 'm44') throw sentinel;
|
||||
return target[key];
|
||||
}});
|
||||
try {call(value);} catch (error) {return error === sentinel && order.join() === names.join();}
|
||||
return false;
|
||||
});
|
||||
check(prefix + '/boolean-does-not-coerce', () => {
|
||||
let conversions = 0;
|
||||
call({is2D: {valueOf() {conversions++; throw Error('boolean coercion');}}});
|
||||
return conversions === 0;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
globalThis.__matrixDictionaryOrderResults = {complete: true, total: checks.length, passed: checks.filter(row => row.passed).length, checks};
|
||||
return true;
|
||||
})()
|
||||
@@ -0,0 +1,23 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn matrix_dictionaries_convert_ancestors_before_own_members() {
|
||||
let mut vm = new_storage_page_task_executor_test_vm("https://matrix-dictionary-order.test/");
|
||||
vm.eval("document.body.innerHTML = '<iframe></iframe>'")
|
||||
.unwrap();
|
||||
vm.eval(include_str!("geometry_matrix_dictionary_order.js"))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
vm.eval("__matrixDictionaryOrderResults.complete").unwrap(),
|
||||
"true"
|
||||
);
|
||||
assert_eq!(
|
||||
vm.eval("__matrixDictionaryOrderResults.total").unwrap(),
|
||||
"1440"
|
||||
);
|
||||
assert_eq!(
|
||||
vm.eval("JSON.stringify(__matrixDictionaryOrderResults.checks.filter(row => !row.passed))")
|
||||
.unwrap(),
|
||||
"[]"
|
||||
);
|
||||
}
|
||||
@@ -2263,6 +2263,7 @@ mod fetch_request_guard;
|
||||
mod fetch_resource_timing;
|
||||
mod frame_element_security;
|
||||
|
||||
mod geometry_matrix_dictionary_order;
|
||||
mod geometry_point_conversion_order;
|
||||
mod headers_list;
|
||||
mod history_document_identity;
|
||||
|
||||
Reference in New Issue
Block a user