mirror of
https://github.com/lexmount/moli.git
synced 2026-10-08 16:01:05 +00:00
fix(geometry): implement DOMQuad
This commit is contained in:
@@ -2468,12 +2468,7 @@ css/cssom/getComputedStyle-layout-dependent-replaced-into-ib-split.html
|
||||
css/cssom/idlharness.html
|
||||
css/cssom/style-sheet-interfaces-001.html
|
||||
css/geometry/DOMMatrix2DInit-validate-fixup.html
|
||||
css/geometry/DOMQuad-001.html
|
||||
css/geometry/DOMQuad-002.html
|
||||
css/geometry/DOMQuad-nan.html
|
||||
css/geometry/DOMRectList.html
|
||||
css/geometry/historical.html
|
||||
css/geometry/spec-examples.html
|
||||
css/geometry/structured-serialization.html
|
||||
css/mediaqueries/at-custom-media-cssom.html
|
||||
css/mediaqueries/at-custom-media-parsing.html
|
||||
|
||||
@@ -3356,10 +3356,15 @@ css/geometry/DOMMatrix-stringifier.html
|
||||
css/geometry/DOMMatrixInit-validate-fixup.html
|
||||
css/geometry/DOMPoint-001.html
|
||||
css/geometry/DOMPoint-002.html
|
||||
css/geometry/DOMQuad-001.html
|
||||
css/geometry/DOMQuad-002.html
|
||||
css/geometry/DOMQuad-nan.html
|
||||
css/geometry/DOMRect-001.html
|
||||
css/geometry/DOMRect-002.html
|
||||
css/geometry/DOMRect-nan.html
|
||||
css/geometry/WebKitCSSMatrix.html
|
||||
css/geometry/historical.html
|
||||
css/geometry/spec-examples.html
|
||||
css/mediaqueries/aspect-ratio-serialization.html
|
||||
css/mediaqueries/duplicate-media-stylesheet-crash.html
|
||||
css/mediaqueries/dynamic-range.html
|
||||
|
||||
@@ -13,6 +13,7 @@ mod crypto;
|
||||
mod css_fontface_runtime;
|
||||
mod css_runtime;
|
||||
pub(crate) mod css_stylesheet_runtime;
|
||||
mod dom_quad;
|
||||
mod dom_rect;
|
||||
mod event_document;
|
||||
mod event_legacy;
|
||||
|
||||
@@ -12,6 +12,7 @@ use super::super::{
|
||||
css_fontface_runtime::font_face_constructor_callback,
|
||||
css_runtime::{css_keyword_value_constructor_callback, css_unit_value_constructor_callback},
|
||||
css_stylesheet_runtime::css_style_sheet_constructor_callback,
|
||||
dom_quad::dom_quad_constructor_callback,
|
||||
events::{
|
||||
EventSubclassKind, ValueEventKind, build_event_subclass_template,
|
||||
build_value_event_template, event_constructor_callback,
|
||||
@@ -527,6 +528,14 @@ pub(in crate::context_bootstrap) fn build_constructor_template<'s>(
|
||||
.length(0)
|
||||
.build(scope)
|
||||
}
|
||||
ConstructorKind::DomQuad => {
|
||||
v8::FunctionTemplate::builder(moli_webapi_declare::web_api_constructor!(
|
||||
web_api_interfaces::DOMQuad,
|
||||
dom_quad_constructor_callback
|
||||
))
|
||||
.length(0)
|
||||
.build(scope)
|
||||
}
|
||||
ConstructorKind::DomMatrix => {
|
||||
v8::FunctionTemplate::builder(dom_matrix_constructor_callback)
|
||||
.length(0)
|
||||
|
||||
@@ -14,6 +14,7 @@ use super::super::{
|
||||
crypto::install_crypto_template_bindings,
|
||||
css_runtime::install_css_typed_om_template_bindings,
|
||||
css_stylesheet_runtime::install_css_stylesheet_template_bindings,
|
||||
dom_quad::install_dom_quad_template_bindings,
|
||||
dom_rect::install_dom_rect_template_bindings,
|
||||
event_template::install_event_template_bindings,
|
||||
file_api::install_file_api_template_bindings,
|
||||
@@ -408,6 +409,7 @@ pub(super) fn install_constructor_template_bindings<'s>(
|
||||
install_css_style_declaration_template_accessors(scope, template, spec.interface.name());
|
||||
install_abort_template_bindings(scope, template, spec.interface.name());
|
||||
install_attr_template_bindings(scope, template, spec.interface.name());
|
||||
install_dom_quad_template_bindings(scope, template, spec.interface.name());
|
||||
install_dom_rect_template_bindings(scope, template, spec.interface.name());
|
||||
install_dom_exception_template_bindings(scope, template, spec.interface.name());
|
||||
install_dom_implementation_template_bindings(scope, template, spec.interface.name());
|
||||
|
||||
@@ -0,0 +1,346 @@
|
||||
use super::*;
|
||||
use crate::{
|
||||
util::{callback_data_index_value, get_private_object},
|
||||
web_api_interfaces, webidl,
|
||||
};
|
||||
use moli_webapi_declare::{WebApiFunctionTemplate, WebApiObject};
|
||||
|
||||
const DOM_QUAD_P1_SLOT: &str = "__moliDomQuadP1";
|
||||
const DOM_QUAD_P2_SLOT: &str = "__moliDomQuadP2";
|
||||
const DOM_QUAD_P3_SLOT: &str = "__moliDomQuadP3";
|
||||
const DOM_QUAD_P4_SLOT: &str = "__moliDomQuadP4";
|
||||
|
||||
#[derive(WebApiObject)]
|
||||
#[webapi(interface = web_api_interfaces::DOMQuad, fallback_to_string_tag = "DOMQuad")]
|
||||
struct DomQuadObjectDeclaration<'scope> {
|
||||
#[webapi(slot = DOM_QUAD_P1_SLOT)]
|
||||
p1: v8::Local<'scope, v8::Object>,
|
||||
#[webapi(slot = DOM_QUAD_P2_SLOT)]
|
||||
p2: v8::Local<'scope, v8::Object>,
|
||||
#[webapi(slot = DOM_QUAD_P3_SLOT)]
|
||||
p3: v8::Local<'scope, v8::Object>,
|
||||
#[webapi(slot = DOM_QUAD_P4_SLOT)]
|
||||
p4: v8::Local<'scope, v8::Object>,
|
||||
}
|
||||
|
||||
#[derive(WebApiObject)]
|
||||
#[webapi(plain, data_properties, enumerable)]
|
||||
struct DomQuadJsonDeclaration<'scope> {
|
||||
p1: v8::Local<'scope, v8::Object>,
|
||||
p2: v8::Local<'scope, v8::Object>,
|
||||
p3: v8::Local<'scope, v8::Object>,
|
||||
p4: v8::Local<'scope, v8::Object>,
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::DOMQuad)]
|
||||
struct DomQuadPrototypeDeclaration {
|
||||
#[webapi(
|
||||
accessor_property,
|
||||
getter = dom_quad_point_getter_callback,
|
||||
data = callback_data_index_value(scope, 0),
|
||||
enumerable
|
||||
)]
|
||||
p1: (),
|
||||
#[webapi(
|
||||
accessor_property,
|
||||
getter = dom_quad_point_getter_callback,
|
||||
data = callback_data_index_value(scope, 1),
|
||||
enumerable
|
||||
)]
|
||||
p2: (),
|
||||
#[webapi(
|
||||
accessor_property,
|
||||
getter = dom_quad_point_getter_callback,
|
||||
data = callback_data_index_value(scope, 2),
|
||||
enumerable
|
||||
)]
|
||||
p3: (),
|
||||
#[webapi(
|
||||
accessor_property,
|
||||
getter = dom_quad_point_getter_callback,
|
||||
data = callback_data_index_value(scope, 3),
|
||||
enumerable
|
||||
)]
|
||||
p4: (),
|
||||
|
||||
#[webapi(
|
||||
method = "getBounds",
|
||||
callback = dom_quad_get_bounds_callback,
|
||||
length = 0,
|
||||
enumerable
|
||||
)]
|
||||
get_bounds: (),
|
||||
|
||||
#[webapi(
|
||||
method = "toJSON",
|
||||
callback = dom_quad_to_json_callback,
|
||||
length = 0,
|
||||
enumerable
|
||||
)]
|
||||
to_json: (),
|
||||
}
|
||||
|
||||
#[derive(WebApiFunctionTemplate)]
|
||||
#[webapi(interface = web_api_interfaces::DOMQuad)]
|
||||
struct DomQuadConstructorDeclaration {
|
||||
#[webapi(
|
||||
static_method = "fromRect",
|
||||
callback = dom_quad_from_rect_callback,
|
||||
length = 0
|
||||
)]
|
||||
from_rect: (),
|
||||
|
||||
#[webapi(
|
||||
static_method = "fromQuad",
|
||||
callback = dom_quad_from_quad_callback,
|
||||
length = 0
|
||||
)]
|
||||
from_quad: (),
|
||||
}
|
||||
|
||||
#[derive(Default, webidl::WebIdlDictionary)]
|
||||
#[webidl(prefix = "DOMQuadInit")]
|
||||
struct DomQuadInit {
|
||||
#[webidl(with = optional_dom_point_member)]
|
||||
p1: Option<geometry_runtime::DomPointInit>,
|
||||
#[webidl(with = optional_dom_point_member)]
|
||||
p2: Option<geometry_runtime::DomPointInit>,
|
||||
#[webidl(with = optional_dom_point_member)]
|
||||
p3: Option<geometry_runtime::DomPointInit>,
|
||||
#[webidl(with = optional_dom_point_member)]
|
||||
p4: Option<geometry_runtime::DomPointInit>,
|
||||
}
|
||||
|
||||
pub(super) fn dom_quad_constructor_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
if !args.is_construct_call() {
|
||||
throw_type_error(
|
||||
scope,
|
||||
"Failed to construct 'DOMQuad': Please use the 'new' operator.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut points = [geometry_runtime::DomPointInit::default(); 4];
|
||||
for (index, point) in points.iter_mut().enumerate() {
|
||||
let Some(init) =
|
||||
geometry_runtime::optional_dom_point_init_arg(scope, &args, index as i32, "DOMQuad")
|
||||
else {
|
||||
return;
|
||||
};
|
||||
*point = init;
|
||||
}
|
||||
|
||||
let [p1, p2, p3, p4] = points.map(|point| build_dom_point(scope, point));
|
||||
DomQuadObjectDeclaration::new(p1, p2, p3, p4)
|
||||
.initialize(scope, args.this())
|
||||
.expect("DOMQuad declaration should initialize object");
|
||||
rv.set(args.this().into());
|
||||
}
|
||||
|
||||
pub(in crate::context_bootstrap) fn install_dom_quad_template_bindings<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_, ()>,
|
||||
template: v8::Local<'s, v8::FunctionTemplate>,
|
||||
interface_name: &str,
|
||||
) {
|
||||
if interface_name != "DOMQuad" {
|
||||
return;
|
||||
}
|
||||
DomQuadConstructorDeclaration::initialize_template(scope, template);
|
||||
DomQuadPrototypeDeclaration::initialize_prototype_template(
|
||||
scope,
|
||||
template.prototype_template(scope),
|
||||
);
|
||||
}
|
||||
|
||||
fn dom_quad_from_rect_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let Some(rect) = dom_rect::dom_rect_init_arg(scope, &args, "DOMQuad.fromRect") else {
|
||||
return;
|
||||
};
|
||||
let p1 = point(rect.x, rect.y);
|
||||
let p2 = point(rect.x + rect.width, rect.y);
|
||||
let p3 = point(rect.x + rect.width, rect.y + rect.height);
|
||||
let p4 = point(rect.x, rect.y + rect.height);
|
||||
rv.set(build_dom_quad(scope, [p1, p2, p3, p4]).into());
|
||||
}
|
||||
|
||||
fn dom_quad_from_quad_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let Some(init) = dom_quad_init_arg(scope, &args) else {
|
||||
return;
|
||||
};
|
||||
rv.set(
|
||||
build_dom_quad(
|
||||
scope,
|
||||
[
|
||||
init.p1.unwrap_or_default(),
|
||||
init.p2.unwrap_or_default(),
|
||||
init.p3.unwrap_or_default(),
|
||||
init.p4.unwrap_or_default(),
|
||||
],
|
||||
)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
|
||||
fn dom_quad_point_getter_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let Some(slot) = callback_data_item(scope, &args, DOM_QUAD_POINT_SLOTS, "DOMQuad point slots")
|
||||
else {
|
||||
rv.set_undefined();
|
||||
return;
|
||||
};
|
||||
if !dom_quad_receiver_branded(scope, args.this()) {
|
||||
throw_type_error(scope, "Illegal invocation");
|
||||
return;
|
||||
}
|
||||
let Some(point) = get_private_object(scope, args.this(), slot) else {
|
||||
rv.set_undefined();
|
||||
return;
|
||||
};
|
||||
rv.set(point.into());
|
||||
}
|
||||
|
||||
fn dom_quad_get_bounds_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let Some(points) = dom_quad_points(scope, args.this()) else {
|
||||
throw_type_error(scope, "Illegal invocation");
|
||||
return;
|
||||
};
|
||||
let points = points.map(|point| geometry_runtime::dom_point_init_from_object(scope, point));
|
||||
let (x, width) = coordinate_bounds(points.map(|point| point.x));
|
||||
let (y, height) = coordinate_bounds(points.map(|point| point.y));
|
||||
rv.set(dom_rect::build_dom_rect_object(scope, x, y, width, height).into());
|
||||
}
|
||||
|
||||
fn dom_quad_to_json_callback<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: v8::FunctionCallbackArguments<'s>,
|
||||
mut rv: v8::ReturnValue<'_, v8::Value>,
|
||||
) {
|
||||
let Some([p1, p2, p3, p4]) = dom_quad_points(scope, args.this()) else {
|
||||
throw_type_error(scope, "Illegal invocation");
|
||||
return;
|
||||
};
|
||||
let Ok(object) = DomQuadJsonDeclaration { p1, p2, p3, p4 }.bind(scope) else {
|
||||
return;
|
||||
};
|
||||
rv.set(object.into());
|
||||
}
|
||||
|
||||
fn build_dom_quad<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
points: [geometry_runtime::DomPointInit; 4],
|
||||
) -> v8::Local<'s, v8::Object> {
|
||||
let [p1, p2, p3, p4] = points.map(|point| build_dom_point(scope, point));
|
||||
DomQuadObjectDeclaration::new(p1, p2, p3, p4)
|
||||
.bind(scope)
|
||||
.expect("DOMQuad declaration should bind")
|
||||
}
|
||||
|
||||
fn build_dom_point<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
point: geometry_runtime::DomPointInit,
|
||||
) -> v8::Local<'s, v8::Object> {
|
||||
geometry_runtime::build_dom_point_object(scope, point.x, point.y, point.z, point.w)
|
||||
}
|
||||
|
||||
fn point(x: f64, y: f64) -> geometry_runtime::DomPointInit {
|
||||
geometry_runtime::DomPointInit {
|
||||
x,
|
||||
y,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn dom_quad_init_arg<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: &v8::FunctionCallbackArguments<'s>,
|
||||
) -> Option<DomQuadInit> {
|
||||
if args.length() == 0 || args.get(0).is_undefined() {
|
||||
return Some(DomQuadInit::default());
|
||||
}
|
||||
match webidl::parse_dictionary::<DomQuadInit>(
|
||||
scope,
|
||||
args.get(0),
|
||||
webidl::Context::argument("DOMQuad.fromQuad", 1),
|
||||
) {
|
||||
Ok(Some(init)) => Some(init),
|
||||
Ok(None) => Some(DomQuadInit::default()),
|
||||
Err(error) => {
|
||||
webidl::throw_error(scope, &error);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn optional_dom_point_member<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
object: v8::Local<'s, v8::Object>,
|
||||
name: &'static str,
|
||||
) -> Result<Option<geometry_runtime::DomPointInit>, webidl::WebIdlError> {
|
||||
let context = webidl::Context::member("DOMQuadInit", name);
|
||||
let Some(value) = webidl::property_result(scope, object, name, context)? else {
|
||||
return Ok(None);
|
||||
};
|
||||
if value.is_undefined() {
|
||||
return Ok(None);
|
||||
}
|
||||
webidl::parse_dictionary::<geometry_runtime::DomPointInit>(scope, value, context)
|
||||
.map(|init| Some(init.unwrap_or_default()))
|
||||
}
|
||||
|
||||
fn dom_quad_points<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
receiver: v8::Local<'s, v8::Object>,
|
||||
) -> Option<[v8::Local<'s, v8::Object>; 4]> {
|
||||
if !dom_quad_receiver_branded(scope, receiver) {
|
||||
return None;
|
||||
}
|
||||
Some([
|
||||
get_private_object(scope, receiver, DOM_QUAD_P1_SLOT)?,
|
||||
get_private_object(scope, receiver, DOM_QUAD_P2_SLOT)?,
|
||||
get_private_object(scope, receiver, DOM_QUAD_P3_SLOT)?,
|
||||
get_private_object(scope, receiver, DOM_QUAD_P4_SLOT)?,
|
||||
])
|
||||
}
|
||||
|
||||
fn dom_quad_receiver_branded<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
receiver: v8::Local<'s, v8::Object>,
|
||||
) -> bool {
|
||||
web_api_interfaces::DOMQuad::is_instance(scope, receiver)
|
||||
}
|
||||
|
||||
fn coordinate_bounds(values: [f64; 4]) -> (f64, f64) {
|
||||
if values.iter().any(|value| value.is_nan()) {
|
||||
return (f64::NAN, f64::NAN);
|
||||
}
|
||||
let minimum = values.into_iter().fold(f64::INFINITY, f64::min);
|
||||
let maximum = values.into_iter().fold(f64::NEG_INFINITY, f64::max);
|
||||
(minimum, maximum - minimum)
|
||||
}
|
||||
|
||||
const DOM_QUAD_POINT_SLOTS: &[&str] = &[
|
||||
DOM_QUAD_P1_SLOT,
|
||||
DOM_QUAD_P2_SLOT,
|
||||
DOM_QUAD_P3_SLOT,
|
||||
DOM_QUAD_P4_SLOT,
|
||||
];
|
||||
@@ -214,15 +214,15 @@ struct DomRectReadOnlyConstructorArgs {
|
||||
|
||||
#[derive(Clone, Copy, Default, webidl::WebIdlDictionary)]
|
||||
#[webidl(prefix = "DOMRectInit")]
|
||||
struct DomRectInit {
|
||||
pub(super) struct DomRectInit {
|
||||
#[webidl(default = 0.0)]
|
||||
x: f64,
|
||||
pub(super) x: f64,
|
||||
#[webidl(default = 0.0)]
|
||||
y: f64,
|
||||
pub(super) y: f64,
|
||||
#[webidl(default = 0.0)]
|
||||
width: f64,
|
||||
pub(super) width: f64,
|
||||
#[webidl(default = 0.0)]
|
||||
height: f64,
|
||||
pub(super) height: f64,
|
||||
}
|
||||
|
||||
pub(super) fn dom_rect_readonly_constructor_callback<'s>(
|
||||
@@ -368,7 +368,7 @@ fn dom_rect_from_rect_callback<'s>(
|
||||
rv.set(build_dom_rect_object(scope, init.x, init.y, init.width, init.height).into());
|
||||
}
|
||||
|
||||
fn dom_rect_init_arg<'s>(
|
||||
pub(super) fn dom_rect_init_arg<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
args: &v8::FunctionCallbackArguments<'s>,
|
||||
prefix: &'static str,
|
||||
|
||||
@@ -1156,6 +1156,18 @@ fn dom_point_slot<'s>(
|
||||
.unwrap_or(default)
|
||||
}
|
||||
|
||||
pub(super) fn dom_point_init_from_object<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
object: v8::Local<'s, v8::Object>,
|
||||
) -> DomPointInit {
|
||||
DomPointInit {
|
||||
x: dom_point_slot(scope, object, DOM_POINT_X_SLOT, 0.0),
|
||||
y: dom_point_slot(scope, object, DOM_POINT_Y_SLOT, 0.0),
|
||||
z: dom_point_slot(scope, object, DOM_POINT_Z_SLOT, 0.0),
|
||||
w: dom_point_slot(scope, object, DOM_POINT_W_SLOT, 1.0),
|
||||
}
|
||||
}
|
||||
|
||||
fn dom_point_receiver_branded<'s>(
|
||||
scope: &mut v8::PinScope<'s, '_>,
|
||||
receiver: v8::Local<'s, v8::Object>,
|
||||
|
||||
@@ -1097,7 +1097,7 @@ const CONSTRUCTOR_SPECS_AFTER_STREAMS: &[ConstructorSpec] = &[
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::DOMQuad::DESCRIPTOR,
|
||||
kind: ConstructorKind::Illegal,
|
||||
kind: ConstructorKind::DomQuad,
|
||||
},
|
||||
ConstructorSpec {
|
||||
interface: web_api_interfaces::DOMMatrixReadOnly::DESCRIPTOR,
|
||||
|
||||
@@ -115,6 +115,7 @@ pub(in crate::context_bootstrap) enum ConstructorKind {
|
||||
DomRect,
|
||||
DomPointReadOnly,
|
||||
DomPoint,
|
||||
DomQuad,
|
||||
DomMatrix,
|
||||
ResizeObserver,
|
||||
PerformanceObserver,
|
||||
|
||||
+137
@@ -518,3 +518,140 @@ fn dom_point_matrix_transform_validates_matrix_init_and_returns_in_the_function_
|
||||
"0|true|false|30,52,12,10|TypeError|TypeError|no throw|no throw"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dom_quad_uses_live_same_object_points_and_geometry_dictionary_factories() {
|
||||
let mut vm = new_storage_test_vm("https://domquad-geometry.test/");
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const probe = callback => {
|
||||
try {
|
||||
return String(callback());
|
||||
} catch (error) {
|
||||
return error.name;
|
||||
}
|
||||
};
|
||||
const q = new DOMQuad(
|
||||
{x: 1, y: 2, z: 3, w: 4},
|
||||
{x: 11, y: 2},
|
||||
{x: 11, y: 22},
|
||||
{x: 1, y: 22}
|
||||
);
|
||||
const initial = [q.p1.x, q.p1.y, q.p1.z, q.p1.w,
|
||||
q.getBounds().x, q.getBounds().y, q.getBounds().width,
|
||||
q.getBounds().height].join(",");
|
||||
const copy = DOMQuad.fromQuad(q);
|
||||
const copyInitial = [copy.p1.x, copy.p1.y, copy.p1.z, copy.p1.w,
|
||||
copy.p4.x, copy.p4.y].join(",");
|
||||
const originalP1 = q.p1;
|
||||
q.p1.x = -5;
|
||||
q.p4.y = 30;
|
||||
q.p1 = new DOMPoint(999, 999);
|
||||
const live = [q.p1 === originalP1, q.p1.x, q.p4.y,
|
||||
q.getBounds().x, q.getBounds().y, q.getBounds().width,
|
||||
q.getBounds().height].join(",");
|
||||
const copyAfterMutation = [copy.p1.x, copy.p4.y, copy.p1 !== q.p1].join(",");
|
||||
const negative = DOMQuad.fromRect({x: 10, y: 20, width: -100, height: -200});
|
||||
const negativeValues = [negative.p1.x, negative.p1.y, negative.p2.x,
|
||||
negative.p3.y, negative.getBounds().x, negative.getBounds().y,
|
||||
negative.getBounds().width, negative.getBounds().height].join(",");
|
||||
const nanBounds = new DOMQuad({x: 0, y: 0}, {x: 0, y: 0},
|
||||
{x: NaN, y: 0}, {x: 0, y: 0}).getBounds();
|
||||
const nanValues = [nanBounds.x, nanBounds.y, nanBounds.width,
|
||||
nanBounds.height].join(",");
|
||||
const json = q.toJSON();
|
||||
const pointDescriptor = Object.getOwnPropertyDescriptor(DOMQuad.prototype, "p1");
|
||||
const fake = Object.assign(Object.create(DOMQuad.prototype), {
|
||||
__moliDomQuadBrand: true,
|
||||
__moliDomQuadP1: new DOMPoint()
|
||||
});
|
||||
return JSON.stringify({
|
||||
interfaceShape: [DOMQuad.length, DOMQuad.fromRect.length,
|
||||
DOMQuad.fromQuad.length, q.getBounds.length, q.toJSON.length,
|
||||
Object.prototype.toString.call(q), "bounds" in q].join("|"),
|
||||
prototypeKeys: Object.keys(DOMQuad.prototype).join(","),
|
||||
pointDescriptor: [typeof pointDescriptor.get, pointDescriptor.get.name,
|
||||
pointDescriptor.get.length, pointDescriptor.set === undefined,
|
||||
pointDescriptor.enumerable, pointDescriptor.configurable].join("|"),
|
||||
sameObject: q.p1 === q.p1,
|
||||
initial,
|
||||
live,
|
||||
copyInitial,
|
||||
copyAfterMutation,
|
||||
negativeValues,
|
||||
nanValues,
|
||||
jsonShape: [Object.getPrototypeOf(json) === Object.prototype,
|
||||
Object.keys(json).join(","), json.p1 === q.p1,
|
||||
JSON.stringify(json)].join("|"),
|
||||
forged: [probe(() => pointDescriptor.get.call(fake)),
|
||||
probe(() => DOMQuad.prototype.getBounds.call(fake)),
|
||||
probe(() => DOMQuad.prototype.toJSON.call(fake))].join(","),
|
||||
visibleSlots: Object.getOwnPropertyNames(q)
|
||||
.filter(name => name.startsWith("__moliDomQuad")).join(",")
|
||||
});
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("DOMQuad geometry probe should evaluate");
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
concat!(
|
||||
r#"{"interfaceShape":"0|0|0|0|0|[object DOMQuad]|false","prototypeKeys":"p1,p2,p3,p4,getBounds,toJSON","pointDescriptor":"function|get p1|0|true|true|true","sameObject":true,"initial":"1,2,3,4,1,2,10,20","live":"true,-5,30,-5,2,16,28","copyInitial":"1,2,3,4,1,22","copyAfterMutation":"1,22,true","negativeValues":"10,20,-90,-180,-90,-180,100,200","nanValues":"NaN,0,NaN,0","jsonShape":"true|p1,p2,p3,p4|true|"#,
|
||||
r#"{\"p1\":{\"x\":-5,\"y\":2,\"z\":3,\"w\":4},\"p2\":{\"x\":11,\"y\":2,\"z\":0,\"w\":1},\"p3\":{\"x\":11,\"y\":22,\"z\":0,\"w\":1},\"p4\":{\"x\":1,\"y\":30,\"z\":0,\"w\":1}}","forged":"TypeError,TypeError,TypeError","visibleSlots":""}"#
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dom_quad_factories_and_default_to_json_use_the_function_realm() {
|
||||
let mut vm = new_storage_test_vm("https://domquad-function-realm.test/");
|
||||
|
||||
vm.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const root = document.documentElement ||
|
||||
document.appendChild(document.createElement("html"));
|
||||
const body = document.body || root.appendChild(document.createElement("body"));
|
||||
const frame = document.createElement("iframe");
|
||||
frame.id = "domquad-function-realm";
|
||||
body.appendChild(frame);
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("DOMQuad factory child frame should be created");
|
||||
materialize_single_child_default_realm_for_test(&mut vm, "DOMQuad factory child Realm");
|
||||
|
||||
let result = vm
|
||||
.eval(
|
||||
r#"
|
||||
(() => {
|
||||
const other = document.getElementById("domquad-function-realm").contentWindow;
|
||||
const quad = other.DOMQuad.fromRect({x: 1, y: 2, width: 3, height: 4});
|
||||
const source = new DOMQuad({x: 7, y: 8});
|
||||
const json = other.DOMQuad.prototype.toJSON.call(source);
|
||||
return [
|
||||
quad instanceof other.DOMQuad,
|
||||
quad instanceof DOMQuad,
|
||||
quad.p1 instanceof other.DOMPoint,
|
||||
quad.p1 instanceof DOMPoint,
|
||||
quad.getBounds() instanceof other.DOMRect,
|
||||
quad.getBounds() instanceof DOMRect,
|
||||
Object.getPrototypeOf(json) === other.Object.prototype,
|
||||
json.p1 === source.p1,
|
||||
json.p1 instanceof DOMPoint,
|
||||
json.p1 instanceof other.DOMPoint
|
||||
].join("|");
|
||||
})()
|
||||
"#,
|
||||
)
|
||||
.expect("DOMQuad function realm probe should evaluate");
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
"true|false|true|false|true|false|true|true|true|false"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user