Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions css/css-variables/url-token-serialization.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Variables: url() token serialization in custom properties</title>
<link rel="help" href="https://drafts.csswg.org/css-variables-2/#serializing-custom-props">
<link rel="help" href="https://drafts.csswg.org/css-syntax-3/#serialization">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="target"></div>
<script>
// "Specified values of custom properties must be serialized exactly as
// specified by the author. Simplifications that might occur in other
// properties, such as dropping comments, normalizing whitespace,
// reserializing numeric tokens from their value, etc., must not occur."
//
// The url() token value should not have its contents escaped using CSS
// identifier serialization rules. Characters like "." and "/" are valid
// in url() tokens and must not be backslash-escaped.

function test_url_roundtrip(input, description) {
test(function() {
var target = document.getElementById('target');
target.style.setProperty('--test', input);
var result = target.style.getPropertyValue('--test');
target.style.removeProperty('--test');
assert_equals(result, input);
}, description);
}

function test_url_serialization(input, expected, description) {
test(function() {
var target = document.getElementById('target');
target.style.setProperty('--test', input);
var result = target.style.getPropertyValue('--test');
target.style.removeProperty('--test');
assert_equals(result, expected);
}, description);
}

test_url_roundtrip(
'url(image.png)',
'Period in url() token must not be escaped'
);

test_url_roundtrip(
'url(path/to/image.png)',
'Slashes and periods in url() token must not be escaped'
);

test_url_roundtrip(
'url(https://example.com/image.png?q=1&v=2#frag)',
'Colons, slashes, periods, question marks, equals, ampersands, and hash in url() token must not be escaped'
);

test_url_roundtrip(
'url(~icons+set!v2)',
'Tilde, plus, and exclamation mark in url() token must not be escaped'
);

test_url_serialization(
'url(foo\\ bar)',
'url(foo\\ bar)',
'Escaped space in url() token must be serialized as an escape'
);

test_url_serialization(
'url(foo\\\tbar)',
'url(foo\\\tbar)',
'Escaped tab in url() token must be serialized as an escape'
);
</script>
58 changes: 58 additions & 0 deletions css/cssom/caretPositionFromPoint-in-flex-container.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<!doctype html>
<meta charset="utf-8">
<title>caretPositionFromPoint in flex/grid containers with tall children</title>
<link rel="help" href="https://drafts.csswg.org/cssom-view-1/#dom-document-caretpositionfrompoint">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<link rel="stylesheet" href="/fonts/ahem.css">
<style>
#container {
display: flex;
flex-direction: column;
width: 200px;
}
/*
* pointer-events:none on the children makes the hit-test return the flex
* container element. The container's positionForPoint must then walk its
* children to find the one closest to the queried point.
*/
.item {
pointer-events: none;
font: 16px/1 Ahem;
}
</style>
<div id="container">
<div id="short" class="item" style="height: 20px">AAA</div>
<div id="tall" class="item" style="height: 300px">BBB</div>
</div>
<script>
test(() => {
const tall = document.getElementById("tall");
const rect = tall.getBoundingClientRect();
// 5 px below #tall's top edge – unambiguously inside #tall.
const pos = document.caretPositionFromPoint(rect.left + 10, rect.top + 5);
assert_not_equals(pos, null, "should return a CaretPosition");
assert_true(tall.contains(pos.offsetNode),
"caret near top of #tall must be inside #tall, not #short");
}, "caretPositionFromPoint just inside a tall flex child resolves to that child");

test(() => {
const tall = document.getElementById("tall");
const rect = tall.getBoundingClientRect();
// 100 px below #tall's top edge – well inside #tall.
const pos = document.caretPositionFromPoint(rect.left + 10, rect.top + 100);
assert_not_equals(pos, null, "should return a CaretPosition");
assert_true(tall.contains(pos.offsetNode),
"caret deep inside #tall must be inside #tall");
}, "caretPositionFromPoint well inside a tall flex child resolves to that child");

test(() => {
const short_ = document.getElementById("short");
const rect = short_.getBoundingClientRect();
// Vertically centred in #short – sanity check.
const pos = document.caretPositionFromPoint(rect.left + 10, rect.top + 10);
assert_not_equals(pos, null, "should return a CaretPosition");
assert_true(short_.contains(pos.offsetNode),
"caret inside #short must be inside #short");
}, "caretPositionFromPoint inside the short flex child resolves correctly");
</script>
141 changes: 141 additions & 0 deletions shadow-dom/event-post-dispatch-no-listeners.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
<!DOCTYPE html>
<title>Shadow DOM: Event properties post dispatch when there are no event listeners</title>
<meta name="author" title="Chris Dumez" href="mailto:cdumez@apple.com">
<link rel="help" href="https://dom.spec.whatwg.org/#concept-event-dispatch">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/shadow-dom.js"></script>

<div id="test1">
<div id="host">
<template id="sr" data-mode="open">
<div id="target"></div>
</template>
</div>
</div>
<script>
test(() => {
const nodes = createTestTree(test1);
document.body.appendChild(nodes.test1);

// Use a unique event type with no listeners registered anywhere in the document.
const event = new Event('unheard-event', { bubbles: true, composed: true });
nodes.target.dispatchEvent(event);

// The event target should be retargeted to the host since the original target
// is inside the shadow tree and the event is composed.
assert_equals(event.target, nodes.host,
'event.target should be the shadow host (retargeted) after dispatch');
assert_equals(event.eventPhase, 0);
assert_equals(event.currentTarget, null);
assert_array_equals(event.composedPath(), []);

nodes.test1.remove();
}, 'Event properties post dispatch with an open ShadowRoot and no listeners (composed: true)');
</script>

<div id="test2">
<div id="host">
<template id="sr" data-mode="open">
<div id="target"></div>
</template>
</div>
</div>
<script>
test(() => {
const nodes = createTestTree(test2);
document.body.appendChild(nodes.test2);

const event = new Event('unheard-event-2', { bubbles: true, composed: false });
nodes.target.dispatchEvent(event);

// Non-composed event stays inside the shadow tree; target should be cleared
// post dispatch since the target's root is a shadow root.
assert_equals(event.target, null,
'event.target should be null for non-composed event inside shadow tree');
assert_equals(event.eventPhase, 0);
assert_equals(event.currentTarget, null);
assert_array_equals(event.composedPath(), []);

nodes.test2.remove();
}, 'Event properties post dispatch with an open ShadowRoot and no listeners (composed: false)');
</script>

<div id="test3">
<div id="host">
<template id="sr" data-mode="closed">
<div id="target"></div>
</template>
</div>
</div>
<script>
test(() => {
const nodes = createTestTree(test3);
document.body.appendChild(nodes.test3);

const event = new Event('unheard-event-3', { bubbles: true, composed: true });
nodes.target.dispatchEvent(event);

assert_equals(event.target, nodes.host,
'event.target should be the shadow host (retargeted) after dispatch');
assert_equals(event.eventPhase, 0);
assert_equals(event.currentTarget, null);
assert_array_equals(event.composedPath(), []);

nodes.test3.remove();
}, 'Event properties post dispatch with a closed ShadowRoot and no listeners (composed: true)');
</script>

<div id="test4">
<div id="host1">
<template id="sr1" data-mode="open">
<div id="host2">
<template id="sr2" data-mode="open">
<div id="target"></div>
</template>
</div>
</template>
</div>
</div>
<script>
test(() => {
const nodes = createTestTree(test4);
document.body.appendChild(nodes.test4);

const event = new Event('unheard-event-4', { bubbles: true, composed: true });
nodes.target.dispatchEvent(event);

assert_equals(event.target, nodes.host1,
'event.target should be the outermost shadow host after dispatch');
assert_equals(event.eventPhase, 0);
assert_equals(event.currentTarget, null);
assert_array_equals(event.composedPath(), []);

nodes.test4.remove();
}, 'Event properties post dispatch with nested open ShadowRoots and no listeners (composed: true)');
</script>

<div id="test5">
<div id="host">
<template id="sr" data-mode="open">
<input id="target" disabled>
</template>
</div>
</div>
<script>
test(() => {
const nodes = createTestTree(test5);
document.body.appendChild(nodes.test5);

const event = new Event('unheard-event-5', { bubbles: true, composed: true });
nodes.target.dispatchEvent(event);

assert_equals(event.target, nodes.host,
'event.target should be the shadow host (retargeted) after dispatch');
assert_equals(event.eventPhase, 0);
assert_equals(event.currentTarget, null);
assert_array_equals(event.composedPath(), []);

nodes.test5.remove();
}, 'Event properties post dispatch with a disabled element in shadow tree and no listeners (composed: true)');
</script>
Loading