Update web-platform-tests to revision 9a5d71b326166e12784bdd9d161772e20f87c1fd
|
@ -1,5 +1,4 @@
|
|||
[url-in-tags-revoke.window.html]
|
||||
expected: TIMEOUT
|
||||
[Fetching a blob URL immediately before revoking it works in an iframe.]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -15,6 +14,3 @@
|
|||
[Opening a blob URL in a new window by clicking an <a> tag works immediately before revoking the URL.]
|
||||
expected: FAIL
|
||||
|
||||
[Fetching a blob URL immediately before revoking it works in <script> tags.]
|
||||
expected: TIMEOUT
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
[registered-property-type.https.html]
|
||||
expected: FAIL
|
|
@ -14,9 +14,6 @@
|
|||
[word-spacing intermediate]
|
||||
expected: FAIL
|
||||
|
||||
[outline-width intermediate]
|
||||
expected: FAIL
|
||||
|
||||
[vertical-align intermediate]
|
||||
expected: FAIL
|
||||
|
||||
|
@ -71,3 +68,15 @@
|
|||
[bottom intermediate]
|
||||
expected: FAIL
|
||||
|
||||
[outline-offset end]
|
||||
expected: FAIL
|
||||
|
||||
[border-bottom-width end]
|
||||
expected: FAIL
|
||||
|
||||
[padding-bottom intermediate]
|
||||
expected: FAIL
|
||||
|
||||
[padding-bottom end]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
[traverse_the_history_1.html]
|
||||
[Multiple history traversals from the same task]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[traverse_the_history_2.html]
|
||||
[Multiple history traversals, last would be aborted]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[composed.window.html]
|
||||
[Focus events are composed]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
[document-level-apis.html]
|
||||
[When a child browsing context is focused, its browsing context container is also focused]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
[focus-fixup-rule-one-no-dialogs.html]
|
||||
[Disabling contenteditable]
|
||||
expected: FAIL
|
||||
|
||||
[Hiding the active element]
|
||||
expected: FAIL
|
||||
|
||||
[Disabling the active element (making it expressly inert)]
|
||||
expected: FAIL
|
||||
|
||||
[Changing the first legend element in disabled <fieldset>]
|
||||
expected: FAIL
|
||||
|
||||
[Disabling <fieldset> affects its descendants]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the tabindex attribute from a div]
|
||||
expected: FAIL
|
||||
|
||||
[Removing the active element from the DOM]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
[preventScroll.html]
|
||||
[Sanity test]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus({preventScroll: false})]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus(null)]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus(undefined)]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus({})]
|
||||
expected: FAIL
|
||||
|
||||
[elm.focus() without arguments]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
[focus-tabindex-default-value.html]
|
||||
[The default value of tabIndex attribute must be 0 for elements that are focusable]
|
||||
expected: FAIL
|
||||
|
||||
[The default value of tabIndex attribute must be -1 for elements that are not focusable]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
[tabindex-focus-flag.html]
|
||||
[a should not be focusable by default.]
|
||||
expected: FAIL
|
||||
|
||||
[#summary-first should be focusable by default.]
|
||||
expected: FAIL
|
||||
|
||||
[input[type="hidden"\] should not be focusable by default.]
|
||||
expected: FAIL
|
||||
|
||||
[[contenteditable\] should be focusable by default.]
|
||||
expected: FAIL
|
||||
|
|
@ -2,15 +2,21 @@
|
|||
[request.formData() with input: a&b&c]
|
||||
expected: FAIL
|
||||
|
||||
[response.formData() with input: _charset_=windows-1252&test=%C2x]
|
||||
expected: FAIL
|
||||
|
||||
[request.formData() with input: a=b&c=d&]
|
||||
expected: FAIL
|
||||
|
||||
[request.formData() with input: a=b&c=d]
|
||||
expected: FAIL
|
||||
|
||||
[request.formData() with input: &&&a=b&&&&c=d&]
|
||||
expected: FAIL
|
||||
|
||||
[response.formData() with input: a=b&c=d&]
|
||||
expected: FAIL
|
||||
|
||||
[response.formData() with input: &&&a=b&&&&c=d&]
|
||||
expected: FAIL
|
||||
|
||||
[response.formData() with input: a=b&c=d]
|
||||
expected: FAIL
|
||||
|
||||
|
||||
[urlencoded-parser.any.worker.html]
|
||||
[response.formData() with input: a&b&c]
|
||||
|
@ -19,18 +25,12 @@
|
|||
[request.formData() with input: a&b&c]
|
||||
expected: FAIL
|
||||
|
||||
[request.formData() with input: &&&a=b&&&&c=d&]
|
||||
expected: FAIL
|
||||
|
||||
[response.formData() with input: a=b&c=d&]
|
||||
expected: FAIL
|
||||
|
||||
[request.formData() with input: a=b&c=d]
|
||||
expected: FAIL
|
||||
|
||||
[request.formData() with input: _charset_=windows-1252&test=%C2x]
|
||||
expected: FAIL
|
||||
|
||||
[response.formData() with input: _charset_=windows-1252&test=%C2x]
|
||||
expected: FAIL
|
||||
|
||||
[response.formData() with input: a=b&c=d]
|
||||
expected: FAIL
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
[buffer-resampling.html]
|
||||
[< [interpolate\] 2 out of 2 assertions were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[# AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed.]
|
||||
expected: FAIL
|
||||
|
||||
[X SNR (0.000 dB) is not greater than or equal to 37.17. Got 0.]
|
||||
expected: FAIL
|
||||
|
||||
[X Interpolated sine wave does not equal [0,0.05756402388215065,0.11493714898824692,0.17192909121513367,0.22835086286067963,0.28401535749435425,0.3387379050254822,0.3923371136188507,0.44463518261909485,0.4954586327075958,0.5446390509605408,0.5920131802558899,0.6374239921569824,0.680720865726471,0.7217602133750916,0.760405957698822...\] with an element-wise tolerance of {"absoluteThreshold":0.090348,"relativeThreshold":0}.\n\tIndex\tActual\t\t\tExpected\t\tAbsError\t\tRelError\t\tTest threshold\n\t[2\]\t0.0000000000000000e+0\t1.1493714898824692e-1\t1.1493714898824692e-1\t1.0000000000000000e+0\t9.0347999999999998e-2\n\t[3\]\t0.0000000000000000e+0\t1.7192909121513367e-1\t1.7192909121513367e-1\t1.0000000000000000e+0\t9.0347999999999998e-2\n\t[4\]\t0.0000000000000000e+0\t2.2835086286067963e-1\t2.2835086286067963e-1\t1.0000000000000000e+0\t9.0347999999999998e-2\n\t[5\]\t0.0000000000000000e+0\t2.8401535749435425e-1\t2.8401535749435425e-1\t1.0000000000000000e+0\t9.0347999999999998e-2\n\t[6\]\t0.0000000000000000e+0\t3.3873790502548218e-1\t3.3873790502548218e-1\t1.0000000000000000e+0\t9.0347999999999998e-2\n\t...and 476 more errors.\n\tMax AbsError of 1.0000000000000000e+0 at index of 300.\n\t[300\]\t0.0000000000000000e+0\t-1.0000000000000000e+0\t1.0000000000000000e+0\t1.0000000000000000e+0\t9.0347999999999998e-2\n\tMax RelError of 1.0000000000000000e+0 at index of 2.\n]
|
||||
expected: FAIL
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Containment Test: contain is not animatable</title>
|
||||
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net/">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-contain/#contain-property">
|
||||
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
|
||||
<meta name=assert content="the contain property is not animatable">
|
||||
<style>
|
||||
div {
|
||||
border: 50px solid green;
|
||||
background: red;
|
||||
position: absolute; /* for shrinkwrap */
|
||||
contain: strict;
|
||||
|
||||
animation-duration: 1s;
|
||||
animation-name: bad;
|
||||
animation-play-state: paused;
|
||||
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
@keyframes bad {
|
||||
from {
|
||||
contain: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div> </div>
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<!doctype html>
|
||||
<html lang=en>
|
||||
<meta charset=utf-8>
|
||||
<title>CSS-contain test: layout containment and baselines</title>
|
||||
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
|
||||
<meta name=assert content="With contain:layout, for the purpose of the vertical-align property, the containing element is treated as having no baseline.">
|
||||
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
|
||||
<link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-layout">
|
||||
<meta name="flags" content="">
|
||||
|
||||
<style>
|
||||
#red {
|
||||
position: absolute;
|
||||
background: red;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
z-index: -1;
|
||||
}
|
||||
.green {
|
||||
display: inline-block;
|
||||
height: 100px;
|
||||
background: green;
|
||||
width: 50px;
|
||||
contain: layout;
|
||||
color: transparent;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||
<div id=red></div>
|
||||
<div class=green></div><div class=green>a</div>
|
|
@ -0,0 +1,24 @@
|
|||
<!doctype html>
|
||||
<html lang=en>
|
||||
<meta charset=utf-8>
|
||||
<title>CSS-contain test: paint containment and baselines</title>
|
||||
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
|
||||
<meta name=assert content="contain:paint does not suppress baseline alignment">
|
||||
<link rel="match" href="reference/contain-baseline-ref.html">
|
||||
<link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-paint">
|
||||
<meta name="flags" content="">
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: inline-block;
|
||||
height: 5px;
|
||||
background: blue;
|
||||
width: 50px;
|
||||
contain: paint;
|
||||
color: transparent;
|
||||
font-size: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there are two, not one, blue lines below.</p>
|
||||
<div></div><div>a</div>
|
|
@ -0,0 +1,24 @@
|
|||
<!doctype html>
|
||||
<html lang=en>
|
||||
<meta charset=utf-8>
|
||||
<title>CSS-contain test: size containment and baselines</title>
|
||||
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
|
||||
<meta name=assert content="contain:size does not suppress baseline alignment">
|
||||
<link rel="match" href="reference/contain-baseline-ref.html">
|
||||
<link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-size">
|
||||
<meta name="flags" content="">
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: inline-block;
|
||||
height: 5px;
|
||||
background: blue;
|
||||
width: 50px;
|
||||
contain: size;
|
||||
color: transparent;
|
||||
font-size: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there are two, not one, blue lines below.</p>
|
||||
<div></div><div>a</div>
|
|
@ -0,0 +1,24 @@
|
|||
<!doctype html>
|
||||
<html lang=en>
|
||||
<meta charset=utf-8>
|
||||
<title>CSS-contain test: style containment and baselines</title>
|
||||
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
|
||||
<meta name=assert content="contain:style does not suppress baseline alignment">
|
||||
<link rel="match" href="reference/contain-baseline-ref.html">
|
||||
<link rel=help href="https://drafts.csswg.org/css-contain-1/#containment-style">
|
||||
<meta name="flags" content="">
|
||||
|
||||
<style>
|
||||
div {
|
||||
display: inline-block;
|
||||
height: 5px;
|
||||
background: blue;
|
||||
width: 50px;
|
||||
contain: style;
|
||||
color: transparent;
|
||||
font-size: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there are two, not one, blue lines below.</p>
|
||||
<div></div><div>a</div>
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<html lang=en>
|
||||
<meta charset=utf-8>
|
||||
<title>CSS test reference</title>
|
||||
<link rel="author" title="Florian Rivoal" href="https://florian.rivoal.net">
|
||||
<style>
|
||||
div {
|
||||
display: inline-block;
|
||||
height: 5px;
|
||||
background: blue;
|
||||
width: 50px;
|
||||
color: transparent;
|
||||
font-size: 100px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<p>Test passes if there are two, not one, blue lines below.</p>
|
||||
<div></div><div>a</div>
|
|
@ -1,67 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<link rel="match" href="parse-input-arguments-ref.html">
|
||||
<style>
|
||||
.container {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
--length: 10px;
|
||||
--number: 10;
|
||||
}
|
||||
|
||||
#canvas-geometry {
|
||||
background-image: paint(geometry);
|
||||
}
|
||||
</style>
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<script src="/common/worklet-reftest.js"></script>
|
||||
<body>
|
||||
<div id="canvas-geometry" class="container"></div>
|
||||
|
||||
<script id="code" type="text/worklet">
|
||||
registerPaint('geometry', class {
|
||||
static get inputProperties() {
|
||||
return [
|
||||
'--length',
|
||||
'--length-initial',
|
||||
'--number',
|
||||
];
|
||||
}
|
||||
paint(ctx, geom, styleMap) {
|
||||
const properties = [...styleMap.keys()].sort();
|
||||
var serializedStrings = [];
|
||||
for (let i = 0; i < properties.length; i++) {
|
||||
const value = styleMap.get(properties[i]);
|
||||
let serialized;
|
||||
if (value)
|
||||
serialized = properties[i].toString() + ': [' + value.constructor.name + '=' + value.toString() + ']';
|
||||
else
|
||||
serialized = properties[i].toString() + ': [null]';
|
||||
serializedStrings.push(serialized);
|
||||
}
|
||||
ctx.strokeStyle = 'green';
|
||||
if (serializedStrings[0] != "--length: [CSSUnitValue=10px]")
|
||||
ctx.strokeStyle = 'red';
|
||||
if (serializedStrings[1] != "--length-initial: [CSSUnitValue=20px]")
|
||||
ctx.strokeStyle = 'blue';
|
||||
if (serializedStrings[2] != "--number: [CSSUnitValue=10]")
|
||||
ctx.strokeStyle = 'yellow';
|
||||
ctx.lineWidth = 4;
|
||||
ctx.strokeRect(0, 0, geom.width, geom.height);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
try {
|
||||
CSS.registerProperty({name: '--length', syntax: '<length>', initialValue: '0px', inherits: false});
|
||||
CSS.registerProperty({name: '--length-initial', syntax: '<length>', initialValue: '20px', inherits: false});
|
||||
CSS.registerProperty({name: '--number', syntax: '<number>', initialValue: '0', inherits: false});
|
||||
importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, document.getElementById('code').textContent);
|
||||
} catch(e) {
|
||||
document.body.textContent = e;
|
||||
takeScreenshot();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,148 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<link rel="help" href="https://www.w3.org/TR/css-paint-api-1/#examples">
|
||||
<link rel="match" href="parse-input-arguments-ref.html">
|
||||
<style>
|
||||
.container {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
#canvas-geometry {
|
||||
background-image: paint(geometry);
|
||||
}
|
||||
</style>
|
||||
<script src="/common/reftest-wait.js"></script>
|
||||
<script src="/common/worklet-reftest.js"></script>
|
||||
<body>
|
||||
<div id="canvas-geometry" class="container"></div>
|
||||
<script id="code" type="text/worklet">
|
||||
// Globals that must be prepended to this script:
|
||||
// - debugLog: A function that logs errors.
|
||||
// - props: Test data.
|
||||
|
||||
registerPaint('geometry', class {
|
||||
static get inputProperties() { return props.map(p => p.name); }
|
||||
|
||||
paint(ctx, geom, styleMap) {
|
||||
ctx.strokeStyle = 'green';
|
||||
for (let prop of props) {
|
||||
let first = styleMap.get(prop.name);
|
||||
let all = styleMap.getAll(prop.name);
|
||||
let serialize = v => v.constructor.name + '=' + v.toString()
|
||||
let actual = all.map(serialize).join(',');
|
||||
let expected = prop.expected.join(',');
|
||||
let pass = actual === expected
|
||||
&& serialize(first) === prop.expected[0];
|
||||
if (!pass)
|
||||
ctx.strokeStyle = 'red';
|
||||
debugLog(pass ? 'PASS' : 'FAIL', prop.syntax, actual, expected);
|
||||
}
|
||||
ctx.lineWidth = 4;
|
||||
ctx.strokeRect(0, 0, geom.width, geom.height);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<script>
|
||||
// A copy of this array (automatically enriched with 'name' and 'expected')
|
||||
// is also available in the worklet.
|
||||
let props = [
|
||||
// Initial values.
|
||||
{ syntax: '*', initialValue: 'if(){}' },
|
||||
{ syntax: '<angle>', initialValue: '42deg' },
|
||||
{ syntax: '<color>', initialValue: '#fefefe' },
|
||||
{ syntax: '<custom-ident>', initialValue: 'none' },
|
||||
{ syntax: '<image>', initialValue: 'linear-gradient(red, red)' },
|
||||
{ syntax: '<image>', initialValue: 'url(http://a.com/a)' },
|
||||
{ syntax: '<integer>', initialValue: '42' },
|
||||
{ syntax: '<length-percentage>', initialValue: '10%' },
|
||||
{ syntax: '<length-percentage>', initialValue: '10px' },
|
||||
{ syntax: '<length-percentage>', initialValue: 'calc(10px + 10%)' },
|
||||
{ syntax: '<length>', initialValue: '1337px' },
|
||||
{ syntax: '<number>', initialValue: '42.5' },
|
||||
{ syntax: '<percentage>', initialValue: '42%' },
|
||||
{ syntax: '<resolution>', initialValue: '300dpi' },
|
||||
{ syntax: '<time>', initialValue: '3600s' },
|
||||
{ syntax: '<url>', initialValue: 'url(http://a.com/a)' },
|
||||
{ syntax: 'thing', initialValue: 'thing' },
|
||||
{ syntax: '<length> | <angle>', initialValue: '1337px' },
|
||||
{ syntax: '<angle> | <image>', initialValue: '1turn' },
|
||||
{ syntax: '<length>+', initialValue: '1337px' },
|
||||
{ syntax: '<length>+', initialValue: '1337px 1338px', count: 2 },
|
||||
{ syntax: '<length>#', initialValue: '1337px' },
|
||||
{ syntax: '<length>#', initialValue: '1337px, 1338px', count: 2 },
|
||||
|
||||
// Non-initial values:
|
||||
{ syntax: '*', initialValue: 'fail', value: 'if(){}' },
|
||||
{ syntax: '<angle> | fail', initialValue: 'fail', value: '42deg' },
|
||||
{ syntax: '<color> | fail', initialValue: 'fail', value: '#fefefe' },
|
||||
{ syntax: '<custom-ident> | fail', initialValue: 'fail', value: 'none' },
|
||||
{ syntax: '<image> | fail', initialValue: 'fail', value: 'linear-gradient(red, red)' },
|
||||
{ syntax: '<image> | fail', initialValue: 'fail', value: 'url(http://a.com/a)' },
|
||||
{ syntax: '<integer> | fail', initialValue: 'fail', value: '42' },
|
||||
{ syntax: '<length-percentage> | fail', initialValue: 'fail', value: '10%' },
|
||||
{ syntax: '<length-percentage> | fail', initialValue: 'fail', value: '10px' },
|
||||
{ syntax: '<length-percentage> | fail', initialValue: 'fail', value: 'calc(10px + 10%)' },
|
||||
{ syntax: '<length> | fail', initialValue: 'fail', value: '1337px' },
|
||||
{ syntax: '<number> | fail', initialValue: 'fail', value: '42.5' },
|
||||
{ syntax: '<percentage> | fail', initialValue: 'fail', value: '42%' },
|
||||
{ syntax: '<resolution> | fail', initialValue: 'fail', value: '300dpi' },
|
||||
{ syntax: '<time> | fail', initialValue: 'fail', value: '3600s' },
|
||||
{ syntax: '<url> | fail', initialValue: 'fail', value: 'url(http://a.com/a)' },
|
||||
{ syntax: 'thing | fail', initialValue: 'fail', value: 'thing' },
|
||||
{ syntax: '<length>+ | fail', initialValue: 'fail', value: '1337px' },
|
||||
{ syntax: '<length>+ | fail', initialValue: 'fail', value: '1337px 1338px', count: 2 },
|
||||
{ syntax: '<length># | fail', initialValue: 'fail', value: '1337px' },
|
||||
{ syntax: '<length># | fail', initialValue: 'fail', value: '1337px, 1338px', count: 2 },
|
||||
];
|
||||
|
||||
try {
|
||||
let target = document.getElementById('canvas-geometry');
|
||||
let pid = 1;
|
||||
|
||||
for (let p of props) {
|
||||
p.name = `--prop-${++pid}`;
|
||||
|
||||
CSS.registerProperty({
|
||||
name: p.name,
|
||||
syntax: p.syntax,
|
||||
initialValue: p.initialValue,
|
||||
inherits: (typeof p.inherits !== 'undefined') ? p.inherits : false
|
||||
});
|
||||
|
||||
if (typeof p.value !== 'undefined')
|
||||
target.style.setProperty(p.name, p.value);
|
||||
if (typeof p.count === 'undefined')
|
||||
p.count = 1;
|
||||
|
||||
let getValue = p => (typeof p.value !== 'undefined') ? p.value : p.initialValue;
|
||||
let serialize = v => v.constructor.name + '=' + v.toString();
|
||||
|
||||
let parse = function (p) {
|
||||
if (p.count == 1)
|
||||
return [CSSStyleValue.parse(p.name, getValue(p))];
|
||||
return CSSStyleValue.parseAll(p.name, getValue(p));
|
||||
};
|
||||
|
||||
// Generate expected value. We assume that CSSStyleValue.parse/All
|
||||
// returns the correct CSSStyleValue subclass and value.
|
||||
p.expected = parse(p).map(serialize);
|
||||
}
|
||||
|
||||
// Adding '?debug' to the URL will cause this test to emit
|
||||
// test results to console.log.
|
||||
let debugMode = document.location.href.endsWith('?debug');
|
||||
let code = [
|
||||
`const props = ${JSON.stringify(props)};`,
|
||||
`const debugLog = ${debugMode ? 'console.log' : 'function(){}'};`,
|
||||
document.getElementById('code').textContent
|
||||
].join('\n');
|
||||
|
||||
importWorkletAndTerminateTestAfterAsyncPaint(CSS.paintWorklet, code);
|
||||
} catch(e) {
|
||||
document.body.textContent = e;
|
||||
takeScreenshot();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="UTF-8">
|
||||
<title>CSS Reference</title>
|
||||
<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||
<style>
|
||||
textarea {
|
||||
overflow: hidden;
|
||||
white-space: pre;
|
||||
}
|
||||
</style>
|
||||
<textarea cols="10" rows="10"></textarea>
|
||||
<script>
|
||||
let textarea = document.querySelector("textarea");
|
||||
textarea.value = ('X'.repeat(100) + '\n').repeat(100);
|
||||
</script>
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="UTF-8">
|
||||
<title>CSS Test: scrollbar-width should apply on <textarea></title>
|
||||
<link rel="author" title="Xidorn Quan" href="https://www.upsuper.org">
|
||||
<link rel="author" title="Mozilla" href="https://www.mozilla.org">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-scrollbars-1/#scrollbar-width">
|
||||
<link rel="match" href="textarea-scrollbar-width-none-ref.html">
|
||||
<style>
|
||||
textarea {
|
||||
scrollbar-width: none;
|
||||
white-space: pre;
|
||||
}
|
||||
</style>
|
||||
<textarea cols="10" rows="10"></textarea>
|
||||
<script>
|
||||
let textarea = document.querySelector("textarea");
|
||||
textarea.value = ('X'.repeat(100) + '\n').repeat(100);
|
||||
</script>
|
|
@ -16,25 +16,25 @@ test_valid_value("offset", "100px none auto 90deg", "100px center none auto 90de
|
|||
test_valid_value("offset", "100px", "100px center");
|
||||
test_valid_value("offset", "auto none reverse");
|
||||
test_valid_value("offset", "auto");
|
||||
test_valid_value("offset", "center bottom path('M 1 2 V 3 Z')");
|
||||
test_valid_value("offset", "center center path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z') 100% 90deg / left bottom");
|
||||
test_valid_value("offset", "center bottom path(\"M 1 2 V 3 Z\")");
|
||||
test_valid_value("offset", "center center path(\"M 0 0 L 100 100 M 100 200 L 200 200 Z L 300 300 Z\") 100% 90deg / left bottom");
|
||||
test_valid_value("offset", "left bottom ray(0rad closest-side) 10px auto 30deg / right bottom");
|
||||
test_valid_value("offset", "left top");
|
||||
test_valid_value("offset", "none 30deg reverse", "none reverse 30deg");
|
||||
test_valid_value("offset", "none 50px reverse 30deg");
|
||||
test_valid_value("offset", "none calc(10px + 20%) auto");
|
||||
test_valid_value("offset", "none reverse");
|
||||
test_valid_value("offset", "path('M 0 0 H 1') -200% auto");
|
||||
test_valid_value("offset", "path('M 0 0 H 1') -200%");
|
||||
test_valid_value("offset", "path('M 0 0 H 1') 50px");
|
||||
test_valid_value("offset", "path('M 0 0 H 1') auto");
|
||||
test_valid_value("offset", "path('M 0 0 H 1') reverse 30deg 50px", "path('M 0 0 H 1') 50px reverse 30deg");
|
||||
test_valid_value("offset", "path('M 0 0 H 1')");
|
||||
test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px / auto", "path('m 0 0 h 100') 8px -7rad / auto");
|
||||
test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px / left top", "path('m 0 0 h 100') 8px -7rad / left top");
|
||||
test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px", "path('m 0 0 h 100') 8px -7rad");
|
||||
test_valid_value("offset", "path('m 0 0 h 100') 100px 0deg");
|
||||
test_valid_value("offset", "path('m 1 2 v 3 Z')");
|
||||
test_valid_value("offset", "path(\"M 0 0 H 1\") -200% auto");
|
||||
test_valid_value("offset", "path(\"M 0 0 H 1\") -200%");
|
||||
test_valid_value("offset", "path('M 0 0 H 1') 50px", "path(\"M 0 0 H 1\") 50px");
|
||||
test_valid_value("offset", "path(\"M 0 0 H 1\") auto");
|
||||
test_valid_value("offset", "path('M 0 0 H 1') reverse 30deg 50px", "path(\"M 0 0 H 1\") 50px reverse 30deg");
|
||||
test_valid_value("offset", "path(\"M 0 0 H 1\")");
|
||||
test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px / auto", "path(\"m 0 0 h 100\") 8px -7rad / auto");
|
||||
test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px / left top", "path(\"m 0 0 h 100\") 8px -7rad / left top");
|
||||
test_valid_value("offset", "path('m 0 0 h 100') -7rad 8px", "path(\"m 0 0 h 100\") 8px -7rad");
|
||||
test_valid_value("offset", "path(\"m 0 0 h 100\") 100px 0deg");
|
||||
test_valid_value("offset", "path('m 1 2 v 3 Z')", "path(\"m 1 2 v 3 Z\")");
|
||||
test_valid_value("offset", "ray(farthest-corner 90deg) 1%", "ray(90deg farthest-corner) 1%");
|
||||
test_valid_value("offset", "ray(sides 0deg) 50% 90deg auto", "ray(0deg sides) 50% auto 90deg");
|
||||
test_valid_value("offset", "right bottom / left top");
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<title>legend focusable</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script>
|
||||
const t = async_test();
|
||||
</script>
|
||||
<fieldset>
|
||||
<legend tabindex=0 onfocus="t.step(() => { t.done(); })">
|
||||
legend
|
||||
<input onfocus="t.unreached_func('input in legend was focused')();">
|
||||
</legend>
|
||||
<input onfocus="t.unreached_func('input after legend was focused')();">
|
||||
</fieldset>
|
||||
<script>
|
||||
document.querySelector('legend').focus();
|
||||
</script>
|
|
@ -0,0 +1,20 @@
|
|||
<!doctype html>
|
||||
<title>legend</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script>
|
||||
const t = async_test();
|
||||
</script>
|
||||
<fieldset>
|
||||
<legend onfocus="t.unreached_func('legend was focused')()">
|
||||
legend
|
||||
<input onfocus="t.unreached_func('input in legend was focused')();">
|
||||
</legend>
|
||||
<input onfocus="t.unreached_func('input after legend was focused')();">
|
||||
</fieldset>
|
||||
<script>
|
||||
document.querySelector('legend').focus();
|
||||
t.step_timeout(() => {
|
||||
t.done();
|
||||
}, 500);
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<!doctype html>
|
||||
<title>legend align does not map to text-align</title>
|
||||
<!-- See discussion in https://bugzilla.mozilla.org/show_bug.cgi?id=1488228 -->
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<style>
|
||||
legend { width: 13em }
|
||||
</style>
|
||||
<fieldset><legend>foo bar abcdefghijklmnopqrstuvwxyz</legend></fieldset>
|
||||
<fieldset><legend align=left>foo bar abcdefghijklmnopqrstuvwxyz</legend></fieldset>
|
||||
<fieldset><legend align=center>foo bar abcdefghijklmnopqrstuvwxyz</legend></fieldset>
|
||||
<fieldset><legend align=right>foo bar abcdefghijklmnopqrstuvwxyz</legend></fieldset>
|
||||
<fieldset><legend align=justify>foo bar abcdefghijklmnopqrstuvwxyz</legend></fieldset>
|
||||
<script>
|
||||
function test_align(selectorTest, expectedAlign) {
|
||||
const testElm = document.querySelector(selectorTest);
|
||||
test(() => {
|
||||
assert_equals(getComputedStyle(testElm).textAlign, expectedAlign);
|
||||
}, selectorTest);
|
||||
}
|
||||
|
||||
test_align('legend', 'start');
|
||||
|
||||
for (const val of ['left', 'center', 'right', 'justify']) {
|
||||
test_align(`legend[align=${val}]`, 'start');
|
||||
}
|
||||
</script>
|
|
@ -5,6 +5,7 @@
|
|||
<fieldset><legend align=left>x</legend></fieldset>
|
||||
<fieldset><legend align=center>x</legend></fieldset>
|
||||
<fieldset><legend align=right>x</legend></fieldset>
|
||||
<fieldset><legend align=justify>x</legend></fieldset>
|
||||
<div align=left>
|
||||
<fieldset><legend>x</legend></fieldset>
|
||||
</div>
|
||||
|
@ -14,6 +15,9 @@
|
|||
<div align=right>
|
||||
<fieldset><legend>x</legend></fieldset>
|
||||
</div>
|
||||
<div align=justify>
|
||||
<fieldset><legend>x</legend></fieldset>
|
||||
</div>
|
||||
<div style="text-align: center">
|
||||
<fieldset><legend>x</legend></fieldset>
|
||||
</div>
|
||||
|
@ -33,12 +37,12 @@ function test_align(selectorTest, selectorRef) {
|
|||
}, selectorTest);
|
||||
}
|
||||
|
||||
for (const val of ['left', 'center', 'right']) {
|
||||
test_align(`div[align=${val}] legend`, `legend[align=${val}]`);
|
||||
for (const val of ['left', 'center', 'right', 'justify']) {
|
||||
test_align(`div[align=${val}] legend`, `legend[align=left]`);
|
||||
}
|
||||
|
||||
test_align(`div[style="text-align: center"] legend`, `legend[align=left]`);
|
||||
test_align(`div[style="text-align: center"][align=center] legend`, `legend[align=center]`);
|
||||
test_align(`div[style="text-align: center"][align=center] legend`, `legend[align=left]`);
|
||||
test_align(`legend[style="margin: 0 auto"]`, `legend[align=center]`);
|
||||
test_align(`legend[style="margin: 0 0 0 auto"]`, `legend[align=right]`);
|
||||
test_align(`fieldset[dir=rtl] legend`, `legend[align=right]`);
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
setup({explicit_done: true, explicit_timeout: true});
|
||||
|
||||
const NOTRUN = 3;
|
||||
let status = NOTRUN;
|
||||
function notrun() {
|
||||
return status === NOTRUN;
|
||||
}
|
||||
add_completion_callback(tests => {
|
||||
status = tests[0].status;
|
||||
});
|
||||
|
||||
function pass() {
|
||||
// Wait a couple of frames in case fail() is also called.
|
||||
requestAnimationFrame(() => {
|
||||
requestAnimationFrame(() => {
|
||||
if (notrun()) {
|
||||
test(() => {});
|
||||
done();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function fail(msg) {
|
||||
if (notrun()) {
|
||||
test(() => { assert_unreached(msg); });
|
||||
done();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const accessKeyElement = document.querySelector('[accesskey]');
|
||||
if (accessKeyElement.accessKeyLabel) {
|
||||
document.querySelector('kbd').textContent = accessKeyElement.accessKeyLabel;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,10 @@
|
|||
<!doctype html>
|
||||
<title>First input after the legend</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=../common/accesskey.js></script>
|
||||
<p>Press the access key combination for "a". <kbd></kbd></p>
|
||||
<fieldset>
|
||||
<legend accesskey=a>legend</legend>
|
||||
<input onfocus="pass()">
|
||||
</fieldset>
|
|
@ -0,0 +1,13 @@
|
|||
<!doctype html>
|
||||
<title>First input before the legend</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=../common/accesskey.js></script>
|
||||
<p>Press the access key combination for "a". <kbd></kbd></p>
|
||||
<fieldset>
|
||||
<input onfocus="pass()">
|
||||
<legend accesskey=a>legend
|
||||
<input onfocus="fail('input in legend was focused')">
|
||||
</legend>
|
||||
<input onfocus="fail('input after legend was focused')">
|
||||
</fieldset>
|
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<title>First input inside the legend</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=../common/accesskey.js></script>
|
||||
<p>Press the access key combination for "a". <kbd></kbd></p>
|
||||
<fieldset>
|
||||
<legend accesskey=a>legend
|
||||
<input onfocus="pass()">
|
||||
</legend>
|
||||
<input onfocus="fail('input after legend was focused')">
|
||||
</fieldset>
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<title>Focusable legend</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=../common/accesskey.js></script>
|
||||
<p>Press the access key combination for "a". <kbd></kbd></p>
|
||||
<fieldset>
|
||||
<legend tabindex=0 onclick="fail('unexpected click event on legend')"
|
||||
onfocus="fail('legend was focused')" accesskey=a>
|
||||
legend
|
||||
<input onfocus="pass()">
|
||||
</legend>
|
||||
<input onfocus="fail('input after legend was focused')">
|
||||
</fieldset>
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<title>Focusable legend sibling</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=../common/accesskey.js></script>
|
||||
<p>Press the access key combination for "a". <kbd></kbd></p>
|
||||
<fieldset>
|
||||
<legend accesskey=a>first legend</legend>
|
||||
<legend tabindex=0 onfocus="fail('sibling legend was focused')">second legend</legend>
|
||||
</fieldset>
|
||||
<script>
|
||||
onkeyup = e => {
|
||||
if (e.keyCode === 65) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,17 @@
|
|||
<!doctype html>
|
||||
<title>Input outside fieldset</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=../common/accesskey.js></script>
|
||||
<p>Press the access key combination for "a". <kbd></kbd></p>
|
||||
<fieldset>
|
||||
<legend accesskey=a>legend</legend>
|
||||
</fieldset>
|
||||
<input onfocus="fail('input outside fieldset was focused')">
|
||||
<script>
|
||||
onkeyup = e => {
|
||||
if (e.keyCode === 65) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<title>Label sibling</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=../common/accesskey.js></script>
|
||||
<p>Press the access key combination for "a". <kbd></kbd></p>
|
||||
<input id=x onfocus="fail('input associated with the label was focused')">
|
||||
<fieldset>
|
||||
<legend accesskey=a>legend</legend>
|
||||
<label for=x onclick="fail('label received a click event')">label</label>
|
||||
</fieldset>
|
||||
<script>
|
||||
onkeyup = e => {
|
||||
if (e.keyCode === 65) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<title>No fieldset parent</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script src=../common/accesskey.js></script>
|
||||
<p>Press the access key combination for "a". <kbd></kbd></p>
|
||||
<legend accesskey=a>
|
||||
legend
|
||||
<input onfocus="fail('input in legend was focused')">
|
||||
</legend>
|
||||
<input onfocus="fail('input after legend was focused')">
|
||||
<script>
|
||||
onkeyup = e => {
|
||||
if (e.keyCode === 65) {
|
||||
pass();
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -7,12 +7,19 @@
|
|||
<script>
|
||||
var worker = 'resources/fetch-event-test-worker.js';
|
||||
|
||||
function do_test(referrer, value, expected, name)
|
||||
{
|
||||
test(() => {
|
||||
assert_equals(value, expected);
|
||||
}, name + (referrer ? " - Custom Referrer" : " - Default Referrer"));
|
||||
}
|
||||
|
||||
function run_referrer_policy_tests(frame, referrer, href, origin) {
|
||||
return frame.contentWindow.fetch('resources/simple.html?referrerFull',
|
||||
{method: "GET", referrer: referrer})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
|
@ -24,7 +31,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: \n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
|
@ -34,7 +41,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
|
@ -46,7 +53,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: \n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
|
@ -56,7 +63,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: origin',
|
||||
|
@ -68,7 +75,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: origin',
|
||||
|
@ -78,7 +85,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: origin-when-cross-origin',
|
||||
|
@ -90,7 +97,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: origin-when-cross-origin',
|
||||
|
@ -100,7 +107,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
|
@ -112,7 +119,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: \n' +
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
|
@ -123,7 +130,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: unsafe-url',
|
||||
|
@ -133,7 +140,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: \n' +
|
||||
'ReferrerPolicy: no-referrer',
|
||||
|
@ -143,7 +150,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: same-origin',
|
||||
|
@ -155,7 +162,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: \n' +
|
||||
'ReferrerPolicy: same-origin',
|
||||
|
@ -167,7 +174,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: strict-origin',
|
||||
|
@ -177,7 +184,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: strict-origin',
|
||||
|
@ -189,7 +196,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: \n' +
|
||||
'ReferrerPolicy: strict-origin',
|
||||
|
@ -199,7 +206,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + href + '\n' +
|
||||
'ReferrerPolicy: strict-origin-when-cross-origin',
|
||||
|
@ -211,7 +218,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: ' + origin + '/' + '\n' +
|
||||
'ReferrerPolicy: strict-origin-when-cross-origin',
|
||||
|
@ -223,7 +230,7 @@ function run_referrer_policy_tests(frame, referrer, href, origin) {
|
|||
})
|
||||
.then(function(response) { return response.text(); })
|
||||
.then(function(response_text) {
|
||||
assert_equals(
|
||||
do_test(referrer,
|
||||
response_text,
|
||||
'Referrer: \n' +
|
||||
'ReferrerPolicy: strict-origin-when-cross-origin',
|
||||
|
@ -241,17 +248,16 @@ async_test(function(t) {
|
|||
.then(function() { return with_iframe(scope); })
|
||||
.then(function(f) {
|
||||
frame = f;
|
||||
assert_equals(
|
||||
frame.contentDocument.body.textContent,
|
||||
'ReferrerPolicy: no-referrer-when-downgrade',
|
||||
'Service Worker should respond to fetch with the default referrer policy');
|
||||
test(() => {
|
||||
assert_equals(frame.contentDocument.body.textContent, 'ReferrerPolicy: no-referrer-when-downgrade');
|
||||
}, 'Service Worker should respond to fetch with the default referrer policy');
|
||||
// First, run the referrer policy tests without passing a referrer in RequestInit.
|
||||
return run_referrer_policy_tests(frame, undefined, frame.contentDocument.location.href,
|
||||
frame.contentDocument.location.origin);
|
||||
})
|
||||
.then(function() {
|
||||
// Now, run the referrer policy tests while passing a referrer in RequestInit.
|
||||
var referrer = get_host_info()['HTTPS_ORIGIN'] + base_path() + 'fake-referrer';
|
||||
var referrer = get_host_info()['HTTPS_ORIGIN'] + base_path() + 'resources/fake-referrer';
|
||||
return run_referrer_policy_tests(frame, 'fake-referrer', referrer,
|
||||
frame.contentDocument.location.origin);
|
||||
})
|
||||
|
|
|
@ -17,27 +17,27 @@
|
|||
// Distinct number of path segments
|
||||
test_no_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 0 0 H 1 H 2')",
|
||||
to: "path('M 0 0 H 3')"
|
||||
from: 'path("M 0 0 H 1 H 2")',
|
||||
to: 'path("M 0 0 H 3")'
|
||||
});
|
||||
|
||||
test_no_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 1 2 L 3 4 Z')",
|
||||
from: 'path("M 1 2 L 3 4 Z")',
|
||||
to: "none"
|
||||
});
|
||||
|
||||
// Distinct segment types
|
||||
test_no_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 10 0 H 11')",
|
||||
to: "path('M 20 0 V 2')"
|
||||
from: 'path("M 10 0 H 11")',
|
||||
to: 'path("M 20 0 V 2")'
|
||||
});
|
||||
|
||||
test_no_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 1 2 L 4 6 Z')",
|
||||
to: "path('M 1 2 H 4 V 6')"
|
||||
from: 'path("M 1 2 L 4 6 Z")',
|
||||
to: 'path("M 1 2 H 4 V 6")'
|
||||
});
|
||||
]]></script>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
|
@ -17,106 +17,106 @@
|
|||
// Mix relative and non-relative
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
|
||||
to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z')"
|
||||
from: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")',
|
||||
to: 'path("M 0 0 L 100 100 m 0 100 l 100 0 z l 300 100 z")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 0 -100 Z')"},
|
||||
{at: 0, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
|
||||
{at: 0.125, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 225 125 Z')"},
|
||||
{at: 0.875, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 375 275 Z')"},
|
||||
{at: 1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 400 300 Z')"},
|
||||
{at: 2, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 600 500 Z')"},
|
||||
{at: -1, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 0 -100 Z")'},
|
||||
{at: 0, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'},
|
||||
{at: 0.125, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 225 125 Z")'},
|
||||
{at: 0.875, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 375 275 Z")'},
|
||||
{at: 1, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 400 300 Z")'},
|
||||
{at: 2, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 600 500 Z")'},
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')",
|
||||
to: "path('M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z')"
|
||||
from: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")',
|
||||
to: 'path("M 0 0 L 100 100 m 0 100 l 100 0 z l 100 -100 z")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
|
||||
{at: 0, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
|
||||
{at: 0.125, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
|
||||
{at: 0.875, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
|
||||
{at: 1, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
|
||||
{at: 2, expect: "path('M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z')"},
|
||||
{at: -1, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'},
|
||||
{at: 0, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'},
|
||||
{at: 0.125, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'},
|
||||
{at: 0.875, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'},
|
||||
{at: 1, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'},
|
||||
{at: 2, expect: 'path("M 0 0 L 100 100 M 100 200 L 200 200 Z L 200 100 Z")'},
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130')",
|
||||
to: "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')"
|
||||
from: 'path("m 10 20 l 40 50 z l 40 60 z m 60 70 l 90 60 z t 70 130")',
|
||||
to: 'path("M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -190 -180 L -70 -50 Z L 10 40 Z M 30 50 L 120 70 Z T 60 220')"},
|
||||
{at: 0, expect: "path('M 10 20 L 50 70 Z L 50 80 Z M 70 90 L 160 150 Z T 140 220')"},
|
||||
{at: 0.125, expect: "path('M 35 45 L 65 85 Z L 55 85 Z M 75 95 L 165 160 Z T 150 220')"},
|
||||
{at: 0.875, expect: "path('M 185 195 L 155 175 Z L 85 115 Z M 105 125 L 195 220 Z T 210 220')"},
|
||||
{at: 1, expect: "path('M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220')"},
|
||||
{at: 2, expect: "path('M 410 420 L 290 310 Z L 130 160 Z M 150 170 L 240 310 Z T 300 220')"}
|
||||
{at: -1, expect: 'path("M -190 -180 L -70 -50 Z L 10 40 Z M 30 50 L 120 70 Z T 60 220")'},
|
||||
{at: 0, expect: 'path("M 10 20 L 50 70 Z L 50 80 Z M 70 90 L 160 150 Z T 140 220")'},
|
||||
{at: 0.125, expect: 'path("M 35 45 L 65 85 Z L 55 85 Z M 75 95 L 165 160 Z T 150 220")'},
|
||||
{at: 0.875, expect: 'path("M 185 195 L 155 175 Z L 85 115 Z M 105 125 L 195 220 Z T 210 220")'},
|
||||
{at: 1, expect: 'path("M 210 220 L 170 190 Z L 90 120 Z M 110 130 L 200 230 Z T 220 220")'},
|
||||
{at: 2, expect: 'path("M 410 420 L 290 310 Z L 130 160 Z M 150 170 L 240 310 Z T 300 220")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160')",
|
||||
to: "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')"
|
||||
from: 'path("m 10 20 c 40 50 30 60 80 70 c 120 130 170 140 110 160")',
|
||||
to: 'path("M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -110 -60 C -30 -10 -40 0 -30 10 C 130 140 180 150 80 170')"},
|
||||
{at: 0, expect: "path('M 10 20 C 50 70 40 80 90 90 C 210 220 260 230 200 250')"},
|
||||
{at: 0.125, expect: "path('M 25 30 C 60 80 50 90 105 100 C 220 230 270 240 215 260')"},
|
||||
{at: 0.875, expect: "path('M 115 90 C 120 140 110 150 195 160 C 280 290 330 300 305 320')"},
|
||||
{at: 1, expect: "path('M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330')"},
|
||||
{at: 2, expect: "path('M 250 180 C 210 230 200 240 330 250 C 370 380 420 390 440 410')"}
|
||||
{at: -1, expect: 'path("M -110 -60 C -30 -10 -40 0 -30 10 C 130 140 180 150 80 170")'},
|
||||
{at: 0, expect: 'path("M 10 20 C 50 70 40 80 90 90 C 210 220 260 230 200 250")'},
|
||||
{at: 0.125, expect: 'path("M 25 30 C 60 80 50 90 105 100 C 220 230 270 240 215 260")'},
|
||||
{at: 0.875, expect: 'path("M 115 90 C 120 140 110 150 195 160 C 280 290 330 300 305 320")'},
|
||||
{at: 1, expect: 'path("M 130 100 C 130 150 120 160 210 170 C 290 300 340 310 320 330")'},
|
||||
{at: 2, expect: 'path("M 250 180 C 210 230 200 240 330 250 C 370 380 420 390 440 410")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 10 20 q 30 60 40 50 q 110 80 90 80')",
|
||||
to: "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')"
|
||||
from: 'path("m 10 20 q 30 60 40 50 q 110 80 90 80")',
|
||||
to: 'path("M 130 100 Q 120 160 130 150 Q 200 150 180 190")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -110 -60 Q -40 0 -30 -10 Q 120 150 100 110')"},
|
||||
{at: 0, expect: "path('M 10 20 Q 40 80 50 70 Q 160 150 140 150')"},
|
||||
{at: 0.125, expect: "path('M 25 30 Q 50 90 60 80 Q 165 150 145 155')"},
|
||||
{at: 0.875, expect: "path('M 115 90 Q 110 150 120 140 Q 195 150 175 185')"},
|
||||
{at: 1, expect: "path('M 130 100 Q 120 160 130 150 Q 200 150 180 190')"},
|
||||
{at: 2, expect: "path('M 250 180 Q 200 240 210 230 Q 240 150 220 230')"}
|
||||
{at: -1, expect: 'path("M -110 -60 Q -40 0 -30 -10 Q 120 150 100 110")'},
|
||||
{at: 0, expect: 'path("M 10 20 Q 40 80 50 70 Q 160 150 140 150")'},
|
||||
{at: 0.125, expect: 'path("M 25 30 Q 50 90 60 80 Q 165 150 145 155")'},
|
||||
{at: 0.875, expect: 'path("M 115 90 Q 110 150 120 140 Q 195 150 175 185")'},
|
||||
{at: 1, expect: 'path("M 130 100 Q 120 160 130 150 Q 200 150 180 190")'},
|
||||
{at: 2, expect: 'path("M 250 180 Q 200 240 210 230 Q 240 150 220 230")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 10 20 s 30 60 40 50 s 110 60 90 70')",
|
||||
to: "path('M 130 140 S 120 160 130 150 S 200 170 140 180')"
|
||||
from: 'path("m 10 20 s 30 60 40 50 s 110 60 90 70")',
|
||||
to: 'path("M 130 140 S 120 160 130 150 S 200 170 140 180")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -110 -100 S -40 0 -30 -10 S 120 90 140 100')"},
|
||||
{at: 0, expect: "path('M 10 20 S 40 80 50 70 S 160 130 140 140')"},
|
||||
{at: 0.125, expect: "path('M 25 35 S 50 90 60 80 S 165 135 140 145')"},
|
||||
{at: 0.875, expect: "path('M 115 125 S 110 150 120 140 S 195 165 140 175')"},
|
||||
{at: 1, expect: "path('M 130 140 S 120 160 130 150 S 200 170 140 180')"},
|
||||
{at: 2, expect: "path('M 250 260 S 200 240 210 230 S 240 210 140 220')"}
|
||||
{at: -1, expect: 'path("M -110 -100 S -40 0 -30 -10 S 120 90 140 100")'},
|
||||
{at: 0, expect: 'path("M 10 20 S 40 80 50 70 S 160 130 140 140")'},
|
||||
{at: 0.125, expect: 'path("M 25 35 S 50 90 60 80 S 165 135 140 145")'},
|
||||
{at: 0.875, expect: 'path("M 115 125 S 110 150 120 140 S 195 165 140 175")'},
|
||||
{at: 1, expect: 'path("M 130 140 S 120 160 130 150 S 200 170 140 180")'},
|
||||
{at: 2, expect: 'path("M 250 260 S 200 240 210 230 S 240 210 140 220")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 10 20 h 30 v 60 h 10 v -10 l 110 60 Z')",
|
||||
to: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z')"
|
||||
from: 'path("m 10 20 h 30 v 60 h 10 v -10 l 110 60 Z")',
|
||||
to: 'path("M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -110 -100 H -40 V 0 H -30 V -10 L 120 90 Z')"},
|
||||
{at: 0, expect: "path('M 10 20 H 40 V 80 H 50 V 70 L 160 130 Z')"},
|
||||
{at: 0.125, expect: "path('M 25 35 H 50 V 90 H 60 V 80 L 165 135 Z')"},
|
||||
{at: 0.875, expect: "path('M 115 125 H 110 V 150 H 120 V 140 L 195 165 Z')"},
|
||||
{at: 1, expect: "path('M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z')"},
|
||||
{at: 2, expect: "path('M 250 260 H 200 V 240 H 210 V 230 L 240 210 Z')"}
|
||||
{at: -1, expect: 'path("M -110 -100 H -40 V 0 H -30 V -10 L 120 90 Z")'},
|
||||
{at: 0, expect: 'path("M 10 20 H 40 V 80 H 50 V 70 L 160 130 Z")'},
|
||||
{at: 0.125, expect: 'path("M 25 35 H 50 V 90 H 60 V 80 L 165 135 Z")'},
|
||||
{at: 0.875, expect: 'path("M 115 125 H 110 V 150 H 120 V 140 L 195 165 Z")'},
|
||||
{at: 1, expect: 'path("M 130 140 H 120 V 160 H 130 V 150 L 200 170 Z")'},
|
||||
{at: 2, expect: 'path("M 250 260 H 200 V 240 H 210 V 230 L 240 210 Z")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50')",
|
||||
to: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')"
|
||||
from: 'path("m 10 20 a 10 20 30 1 0 40 50 a 110 120 30 1 1 140 50")',
|
||||
to: 'path("M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 2 28 A -30 -60 -10 1 0 10 30 A 70 80 -10 1 1 310 160')"},
|
||||
{at: 0, expect: "path('M 10 20 A 10 20 30 1 0 50 70 A 110 120 30 1 1 190 120')"},
|
||||
{at: 0.125, expect: "path('M 11 19 A 15 30 35 1 0 55 75 A 115 125 35 1 1 175 115')"},
|
||||
{at: 0.875, expect: "path('M 17 13 A 45 90 65 0 1 85 105 A 145 155 65 0 1 85 85')"},
|
||||
{at: 1, expect: "path('M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80')"},
|
||||
{at: 2, expect: "path('M 26 4 A 90 180 110 0 1 130 150 A 190 200 110 0 1 -50 40')"}
|
||||
{at: -1, expect: 'path("M 2 28 A -30 -60 -10 1 0 10 30 A 70 80 -10 1 1 310 160")'},
|
||||
{at: 0, expect: 'path("M 10 20 A 10 20 30 1 0 50 70 A 110 120 30 1 1 190 120")'},
|
||||
{at: 0.125, expect: 'path("M 11 19 A 15 30 35 1 0 55 75 A 115 125 35 1 1 175 115")'},
|
||||
{at: 0.875, expect: 'path("M 17 13 A 45 90 65 0 1 85 105 A 145 155 65 0 1 85 85")'},
|
||||
{at: 1, expect: 'path("M 18 12 A 50 100 70 0 1 90 110 A 150 160 70 0 1 70 80")'},
|
||||
{at: 2, expect: 'path("M 26 4 A 90 180 110 0 1 130 150 A 190 200 110 0 1 -50 40")'}
|
||||
]);
|
||||
]]></script>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.4 KiB |
|
@ -17,229 +17,229 @@
|
|||
// Exercise each segment type
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 20 70')",
|
||||
to: "path('M 100 30')"
|
||||
from: 'path("M 20 70")',
|
||||
to: 'path("M 100 30")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -60 110')"},
|
||||
{at: 0, expect: "path('M 20 70')"},
|
||||
{at: 0.125, expect: "path('M 30 65')"},
|
||||
{at: 0.875, expect: "path('M 90 35')"},
|
||||
{at: 1, expect: "path('M 100 30')"},
|
||||
{at: 2, expect: "path('M 180 -10')"}
|
||||
{at: -1, expect: 'path("M -60 110")'},
|
||||
{at: 0, expect: 'path("M 20 70")'},
|
||||
{at: 0.125, expect: 'path("M 30 65")'},
|
||||
{at: 0.875, expect: 'path("M 90 35")'},
|
||||
{at: 1, expect: 'path("M 100 30")'},
|
||||
{at: 2, expect: 'path("M 180 -10")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 20 70')",
|
||||
to: "path('m 100 30')"
|
||||
from: 'path("m 20 70")',
|
||||
to: 'path("m 100 30")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -60 110')"},
|
||||
{at: 0, expect: "path('M 20 70')"},
|
||||
{at: 0.125, expect: "path('M 30 65')"},
|
||||
{at: 0.875, expect: "path('M 90 35')"},
|
||||
{at: 1, expect: "path('M 100 30')"},
|
||||
{at: 2, expect: "path('M 180 -10')"}
|
||||
{at: -1, expect: 'path("M -60 110")'},
|
||||
{at: 0, expect: 'path("M 20 70")'},
|
||||
{at: 0.125, expect: 'path("M 30 65")'},
|
||||
{at: 0.875, expect: 'path("M 90 35")'},
|
||||
{at: 1, expect: 'path("M 100 30")'},
|
||||
{at: 2, expect: 'path("M 180 -10")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 100 200 L 120 270')",
|
||||
to: "path('m 100 200 L 200 230')"
|
||||
from: 'path("m 100 200 L 120 270")',
|
||||
to: 'path("m 100 200 L 200 230")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 100 200 L 40 310')"},
|
||||
{at: 0, expect: "path('M 100 200 L 120 270')"},
|
||||
{at: 0.125, expect: "path('M 100 200 L 130 265')"},
|
||||
{at: 0.875, expect: "path('M 100 200 L 190 235')"},
|
||||
{at: 1, expect: "path('M 100 200 L 200 230')"},
|
||||
{at: 2, expect: "path('M 100 200 L 280 190')"}
|
||||
{at: -1, expect: 'path("M 100 200 L 40 310")'},
|
||||
{at: 0, expect: 'path("M 100 200 L 120 270")'},
|
||||
{at: 0.125, expect: 'path("M 100 200 L 130 265")'},
|
||||
{at: 0.875, expect: 'path("M 100 200 L 190 235")'},
|
||||
{at: 1, expect: 'path("M 100 200 L 200 230")'},
|
||||
{at: 2, expect: 'path("M 100 200 L 280 190")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 100 200 l 20 70')",
|
||||
to: "path('m 100 200 l 100 30')"
|
||||
from: 'path("m 100 200 l 20 70")',
|
||||
to: 'path("m 100 200 l 100 30")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 100 200 L 40 310')"},
|
||||
{at: 0, expect: "path('M 100 200 L 120 270')"},
|
||||
{at: 0.125, expect: "path('M 100 200 L 130 265')"},
|
||||
{at: 0.875, expect: "path('M 100 200 L 190 235')"},
|
||||
{at: 1, expect: "path('M 100 200 L 200 230')"},
|
||||
{at: 2, expect: "path('M 100 200 L 280 190')"}
|
||||
{at: -1, expect: 'path("M 100 200 L 40 310")'},
|
||||
{at: 0, expect: 'path("M 100 200 L 120 270")'},
|
||||
{at: 0.125, expect: 'path("M 100 200 L 130 265")'},
|
||||
{at: 0.875, expect: 'path("M 100 200 L 190 235")'},
|
||||
{at: 1, expect: 'path("M 100 200 L 200 230")'},
|
||||
{at: 2, expect: 'path("M 100 200 L 280 190")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 20 10 C 32 42 52 62 120 2200')",
|
||||
to: "path('M 20 10 C 40 50 60 70 200 3000')",
|
||||
from: 'path("M 20 10 C 32 42 52 62 120 2200")',
|
||||
to: 'path("M 20 10 C 40 50 60 70 200 3000")',
|
||||
}, [
|
||||
{at: -1, expect: "path('M 20 10 C 24 34 44 54 40 1400')"},
|
||||
{at: 0, expect: "path('M 20 10 C 32 42 52 62 120 2200')"},
|
||||
{at: 0.125, expect: "path('M 20 10 C 33 43 53 63 130 2300')"},
|
||||
{at: 0.875, expect: "path('M 20 10 C 39 49 59 69 190 2900')"},
|
||||
{at: 1, expect: "path('M 20 10 C 40 50 60 70 200 3000')"},
|
||||
{at: 2, expect: "path('M 20 10 C 48 58 68 78 280 3800')"}
|
||||
{at: -1, expect: 'path("M 20 10 C 24 34 44 54 40 1400")'},
|
||||
{at: 0, expect: 'path("M 20 10 C 32 42 52 62 120 2200")'},
|
||||
{at: 0.125, expect: 'path("M 20 10 C 33 43 53 63 130 2300")'},
|
||||
{at: 0.875, expect: 'path("M 20 10 C 39 49 59 69 190 2900")'},
|
||||
{at: 1, expect: 'path("M 20 10 C 40 50 60 70 200 3000")'},
|
||||
{at: 2, expect: 'path("M 20 10 C 48 58 68 78 280 3800")'}
|
||||
]);
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 20 10 c 12 32 32 52 100 2190')",
|
||||
to: "path('m 20 10 c 20 40 40 60 180 2990')"
|
||||
from: 'path("m 20 10 c 12 32 32 52 100 2190")',
|
||||
to: 'path("m 20 10 c 20 40 40 60 180 2990")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 20 10 C 24 34 44 54 40 1400')"},
|
||||
{at: 0, expect: "path('M 20 10 C 32 42 52 62 120 2200')"},
|
||||
{at: 0.125, expect: "path('M 20 10 C 33 43 53 63 130 2300')"},
|
||||
{at: 0.875, expect: "path('M 20 10 C 39 49 59 69 190 2900')"},
|
||||
{at: 1, expect: "path('M 20 10 C 40 50 60 70 200 3000')"},
|
||||
{at: 2, expect: "path('M 20 10 C 48 58 68 78 280 3800')"}
|
||||
{at: -1, expect: 'path("M 20 10 C 24 34 44 54 40 1400")'},
|
||||
{at: 0, expect: 'path("M 20 10 C 32 42 52 62 120 2200")'},
|
||||
{at: 0.125, expect: 'path("M 20 10 C 33 43 53 63 130 2300")'},
|
||||
{at: 0.875, expect: 'path("M 20 10 C 39 49 59 69 190 2900")'},
|
||||
{at: 1, expect: 'path("M 20 10 C 40 50 60 70 200 3000")'},
|
||||
{at: 2, expect: 'path("M 20 10 C 48 58 68 78 280 3800")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 20 10 Q 32 42 120 2200')",
|
||||
to: "path('M 20 10 Q 40 50 200 3000')"
|
||||
from: 'path("M 20 10 Q 32 42 120 2200")',
|
||||
to: 'path("M 20 10 Q 40 50 200 3000")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 20 10 Q 24 34 40 1400')"},
|
||||
{at: 0, expect: "path('M 20 10 Q 32 42 120 2200')"},
|
||||
{at: 0.125, expect: "path('M 20 10 Q 33 43 130 2300')"},
|
||||
{at: 0.875, expect: "path('M 20 10 Q 39 49 190 2900')"},
|
||||
{at: 1, expect: "path('M 20 10 Q 40 50 200 3000')"},
|
||||
{at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"}
|
||||
{at: -1, expect: 'path("M 20 10 Q 24 34 40 1400")'},
|
||||
{at: 0, expect: 'path("M 20 10 Q 32 42 120 2200")'},
|
||||
{at: 0.125, expect: 'path("M 20 10 Q 33 43 130 2300")'},
|
||||
{at: 0.875, expect: 'path("M 20 10 Q 39 49 190 2900")'},
|
||||
{at: 1, expect: 'path("M 20 10 Q 40 50 200 3000")'},
|
||||
{at: 2, expect: 'path("M 20 10 Q 48 58 280 3800")'}
|
||||
]);
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 20 10 q 12 32 100 2190')",
|
||||
to: "path('m 20 10 q 20 40 180 2990')"
|
||||
from: 'path("m 20 10 q 12 32 100 2190")',
|
||||
to: 'path("m 20 10 q 20 40 180 2990")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 20 10 Q 24 34 40 1400')"},
|
||||
{at: 0, expect: "path('M 20 10 Q 32 42 120 2200')"},
|
||||
{at: 0.125, expect: "path('M 20 10 Q 33 43 130 2300')"},
|
||||
{at: 0.875, expect: "path('M 20 10 Q 39 49 190 2900')"},
|
||||
{at: 1, expect: "path('M 20 10 Q 40 50 200 3000')"},
|
||||
{at: 2, expect: "path('M 20 10 Q 48 58 280 3800')"}
|
||||
{at: -1, expect: 'path("M 20 10 Q 24 34 40 1400")'},
|
||||
{at: 0, expect: 'path("M 20 10 Q 32 42 120 2200")'},
|
||||
{at: 0.125, expect: 'path("M 20 10 Q 33 43 130 2300")'},
|
||||
{at: 0.875, expect: 'path("M 20 10 Q 39 49 190 2900")'},
|
||||
{at: 1, expect: 'path("M 20 10 Q 40 50 200 3000")'},
|
||||
{at: 2, expect: 'path("M 20 10 Q 48 58 280 3800")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 100 400 A 10 20 30 1 0 140 450')",
|
||||
to: "path('M 300 200 A 50 60 70 0 1 380 290')"
|
||||
from: 'path("M 100 400 A 10 20 30 1 0 140 450")',
|
||||
to: 'path("M 300 200 A 50 60 70 0 1 380 290")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"},
|
||||
{at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"},
|
||||
{at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"},
|
||||
{at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"},
|
||||
{at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"},
|
||||
{at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"}
|
||||
{at: -1, expect: 'path("M -100 600 A -30 -20 -10 1 0 -100 610")'},
|
||||
{at: 0, expect: 'path("M 100 400 A 10 20 30 1 0 140 450")'},
|
||||
{at: 0.125, expect: 'path("M 125 375 A 15 25 35 1 0 170 430")'},
|
||||
{at: 0.875, expect: 'path("M 275 225 A 45 55 65 0 1 350 310")'},
|
||||
{at: 1, expect: 'path("M 300 200 A 50 60 70 0 1 380 290")'},
|
||||
{at: 2, expect: 'path("M 500 0 A 90 100 110 0 1 620 130")'}
|
||||
]);
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 100 400 a 10 20 30 1 0 40 50')",
|
||||
to: "path('m 300 200 a 50 60 70 0 1 80 90')"
|
||||
from: 'path("m 100 400 a 10 20 30 1 0 40 50")',
|
||||
to: 'path("m 300 200 a 50 60 70 0 1 80 90")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M -100 600 A -30 -20 -10 1 0 -100 610')"},
|
||||
{at: 0, expect: "path('M 100 400 A 10 20 30 1 0 140 450')"},
|
||||
{at: 0.125, expect: "path('M 125 375 A 15 25 35 1 0 170 430')"},
|
||||
{at: 0.875, expect: "path('M 275 225 A 45 55 65 0 1 350 310')"},
|
||||
{at: 1, expect: "path('M 300 200 A 50 60 70 0 1 380 290')"},
|
||||
{at: 2, expect: "path('M 500 0 A 90 100 110 0 1 620 130')"}
|
||||
{at: -1, expect: 'path("M -100 600 A -30 -20 -10 1 0 -100 610")'},
|
||||
{at: 0, expect: 'path("M 100 400 A 10 20 30 1 0 140 450")'},
|
||||
{at: 0.125, expect: 'path("M 125 375 A 15 25 35 1 0 170 430")'},
|
||||
{at: 0.875, expect: 'path("M 275 225 A 45 55 65 0 1 350 310")'},
|
||||
{at: 1, expect: 'path("M 300 200 A 50 60 70 0 1 380 290")'},
|
||||
{at: 2, expect: 'path("M 500 0 A 90 100 110 0 1 620 130")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 50 60 H 70')",
|
||||
to: "path('M 10 140 H 270')"
|
||||
from: 'path("M 50 60 H 70")',
|
||||
to: 'path("M 10 140 H 270")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 90 -20 H -130')"},
|
||||
{at: 0, expect: "path('M 50 60 H 70')"},
|
||||
{at: 0.125, expect: "path('M 45 70 H 95')"},
|
||||
{at: 0.875, expect: "path('M 15 130 H 245')"},
|
||||
{at: 1, expect: "path('M 10 140 H 270')"},
|
||||
{at: 2, expect: "path('M -30 220 H 470')"}
|
||||
{at: -1, expect: 'path("M 90 -20 H -130")'},
|
||||
{at: 0, expect: 'path("M 50 60 H 70")'},
|
||||
{at: 0.125, expect: 'path("M 45 70 H 95")'},
|
||||
{at: 0.875, expect: 'path("M 15 130 H 245")'},
|
||||
{at: 1, expect: 'path("M 10 140 H 270")'},
|
||||
{at: 2, expect: 'path("M -30 220 H 470")'}
|
||||
]);
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 50 60 h 20')",
|
||||
to: "path('m 10 140 h 260')"
|
||||
from: 'path("m 50 60 h 20")',
|
||||
to: 'path("m 10 140 h 260")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 90 -20 H -130')"},
|
||||
{at: 0, expect: "path('M 50 60 H 70')"},
|
||||
{at: 0.125, expect: "path('M 45 70 H 95')"},
|
||||
{at: 0.875, expect: "path('M 15 130 H 245')"},
|
||||
{at: 1, expect: "path('M 10 140 H 270')"},
|
||||
{at: 2, expect: "path('M -30 220 H 470')"}
|
||||
{at: -1, expect: 'path("M 90 -20 H -130")'},
|
||||
{at: 0, expect: 'path("M 50 60 H 70")'},
|
||||
{at: 0.125, expect: 'path("M 45 70 H 95")'},
|
||||
{at: 0.875, expect: 'path("M 15 130 H 245")'},
|
||||
{at: 1, expect: 'path("M 10 140 H 270")'},
|
||||
{at: 2, expect: 'path("M -30 220 H 470")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 50 60 V 70')",
|
||||
to: "path('M 10 140 V 270')"
|
||||
from: 'path("M 50 60 V 70")',
|
||||
to: 'path("M 10 140 V 270")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 90 -20 V -130')"},
|
||||
{at: 0, expect: "path('M 50 60 V 70')"},
|
||||
{at: 0.125, expect: "path('M 45 70 V 95')"},
|
||||
{at: 0.875, expect: "path('M 15 130 V 245')"},
|
||||
{at: 1, expect: "path('M 10 140 V 270')"},
|
||||
{at: 2, expect: "path('M -30 220 V 470')"}
|
||||
{at: -1, expect: 'path("M 90 -20 V -130")'},
|
||||
{at: 0, expect: 'path("M 50 60 V 70")'},
|
||||
{at: 0.125, expect: 'path("M 45 70 V 95")'},
|
||||
{at: 0.875, expect: 'path("M 15 130 V 245")'},
|
||||
{at: 1, expect: 'path("M 10 140 V 270")'},
|
||||
{at: 2, expect: 'path("M -30 220 V 470")'}
|
||||
]);
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 50 60 v 10')",
|
||||
to: "path('m 10 140 v 130')"
|
||||
from: 'path("m 50 60 v 10")',
|
||||
to: 'path("m 10 140 v 130")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 90 -20 V -130')"},
|
||||
{at: 0, expect: "path('M 50 60 V 70')"},
|
||||
{at: 0.125, expect: "path('M 45 70 V 95')"},
|
||||
{at: 0.875, expect: "path('M 15 130 V 245')"},
|
||||
{at: 1, expect: "path('M 10 140 V 270')"},
|
||||
{at: 2, expect: "path('M -30 220 V 470')"}
|
||||
{at: -1, expect: 'path("M 90 -20 V -130")'},
|
||||
{at: 0, expect: 'path("M 50 60 V 70")'},
|
||||
{at: 0.125, expect: 'path("M 45 70 V 95")'},
|
||||
{at: 0.875, expect: 'path("M 15 130 V 245")'},
|
||||
{at: 1, expect: 'path("M 10 140 V 270")'},
|
||||
{at: 2, expect: 'path("M -30 220 V 470")'}
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 12 34 S 45 67 89 123')",
|
||||
to: "path('M 20 26 S 61 51 113 99')"
|
||||
from: 'path("M 12 34 S 45 67 89 123")',
|
||||
to: 'path("M 20 26 S 61 51 113 99")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 4 42 S 29 83 65 147')"},
|
||||
{at: 0, expect: "path('M 12 34 S 45 67 89 123')"},
|
||||
{at: 0.125, expect: "path('M 13 33 S 47 65 92 120')"},
|
||||
{at: 0.875, expect: "path('M 19 27 S 59 53 110 102')"},
|
||||
{at: 1, expect: "path('M 20 26 S 61 51 113 99')"},
|
||||
{at: 2, expect: "path('M 28 18 S 77 35 137 75')"},
|
||||
{at: -1, expect: 'path("M 4 42 S 29 83 65 147")'},
|
||||
{at: 0, expect: 'path("M 12 34 S 45 67 89 123")'},
|
||||
{at: 0.125, expect: 'path("M 13 33 S 47 65 92 120")'},
|
||||
{at: 0.875, expect: 'path("M 19 27 S 59 53 110 102")'},
|
||||
{at: 1, expect: 'path("M 20 26 S 61 51 113 99")'},
|
||||
{at: 2, expect: 'path("M 28 18 S 77 35 137 75")'},
|
||||
]);
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 12 34 s 33 33 77 89')",
|
||||
to: "path('m 20 26 s 41 25 93 73')"
|
||||
from: 'path("m 12 34 s 33 33 77 89")',
|
||||
to: 'path("m 20 26 s 41 25 93 73")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 4 42 S 29 83 65 147')"},
|
||||
{at: 0, expect: "path('M 12 34 S 45 67 89 123')"},
|
||||
{at: 0.125, expect: "path('M 13 33 S 47 65 92 120')"},
|
||||
{at: 0.875, expect: "path('M 19 27 S 59 53 110 102')"},
|
||||
{at: 1, expect: "path('M 20 26 S 61 51 113 99')"},
|
||||
{at: 2, expect: "path('M 28 18 S 77 35 137 75')"},
|
||||
{at: -1, expect: 'path("M 4 42 S 29 83 65 147")'},
|
||||
{at: 0, expect: 'path("M 12 34 S 45 67 89 123")'},
|
||||
{at: 0.125, expect: 'path("M 13 33 S 47 65 92 120")'},
|
||||
{at: 0.875, expect: 'path("M 19 27 S 59 53 110 102")'},
|
||||
{at: 1, expect: 'path("M 20 26 S 61 51 113 99")'},
|
||||
{at: 2, expect: 'path("M 28 18 S 77 35 137 75")'},
|
||||
]);
|
||||
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('M 12 34 T 45 67')",
|
||||
to: "path('M 20 26 T 61 51')"
|
||||
from: 'path("M 12 34 T 45 67")',
|
||||
to: 'path("M 20 26 T 61 51")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 4 42 T 29 83')"},
|
||||
{at: 0, expect: "path('M 12 34 T 45 67')"},
|
||||
{at: 0.125, expect: "path('M 13 33 T 47 65')"},
|
||||
{at: 0.875, expect: "path('M 19 27 T 59 53')"},
|
||||
{at: 1, expect: "path('M 20 26 T 61 51')"},
|
||||
{at: 2, expect: "path('M 28 18 T 77 35')"},
|
||||
{at: -1, expect: 'path("M 4 42 T 29 83")'},
|
||||
{at: 0, expect: 'path("M 12 34 T 45 67")'},
|
||||
{at: 0.125, expect: 'path("M 13 33 T 47 65")'},
|
||||
{at: 0.875, expect: 'path("M 19 27 T 59 53")'},
|
||||
{at: 1, expect: 'path("M 20 26 T 61 51")'},
|
||||
{at: 2, expect: 'path("M 28 18 T 77 35")'},
|
||||
]);
|
||||
test_interpolation({
|
||||
property: 'd',
|
||||
from: "path('m 12 34 t 33 33')",
|
||||
to: "path('m 20 26 t 41 25')"
|
||||
from: 'path("m 12 34 t 33 33")',
|
||||
to: 'path("m 20 26 t 41 25")'
|
||||
}, [
|
||||
{at: -1, expect: "path('M 4 42 T 29 83')"},
|
||||
{at: 0, expect: "path('M 12 34 T 45 67')"},
|
||||
{at: 0.125, expect: "path('M 13 33 T 47 65')"},
|
||||
{at: 0.875, expect: "path('M 19 27 T 59 53')"},
|
||||
{at: 1, expect: "path('M 20 26 T 61 51')"},
|
||||
{at: 2, expect: "path('M 28 18 T 77 35')"},
|
||||
{at: -1, expect: 'path("M 4 42 T 29 83")'},
|
||||
{at: 0, expect: 'path("M 12 34 T 45 67")'},
|
||||
{at: 0.125, expect: 'path("M 13 33 T 47 65")'},
|
||||
{at: 0.875, expect: 'path("M 19 27 T 59 53")'},
|
||||
{at: 1, expect: 'path("M 20 26 T 61 51")'},
|
||||
{at: 2, expect: 'path("M 28 18 T 77 35")'},
|
||||
]);
|
||||
]]></script>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
|
@ -39,14 +39,14 @@
|
|||
var p6 = document.getElementById('p6');
|
||||
var p7 = document.getElementById('p7');
|
||||
|
||||
assert_equals(getComputedStyle(g0).d, "none");
|
||||
assert_equals(getComputedStyle(p1).d, "none");
|
||||
assert_equals(getComputedStyle(p2).d, "path('M 10 2 H 20')");
|
||||
assert_equals(getComputedStyle(p3).d, "path('M 10 3 H 30')");
|
||||
assert_equals(getComputedStyle(p4).d, "path('M 10 4 H 40')");
|
||||
assert_equals(getComputedStyle(g5).d, "path('M 10 5 H 50')");
|
||||
assert_equals(getComputedStyle(p6).d, "path('M 10 5 H 50')");
|
||||
assert_equals(getComputedStyle(p7).d, "none");
|
||||
assert_equals(getComputedStyle(g0).d, 'none');
|
||||
assert_equals(getComputedStyle(p1).d, 'none');
|
||||
assert_equals(getComputedStyle(p2).d, 'path("M 10 2 H 20")');
|
||||
assert_equals(getComputedStyle(p3).d, 'path("M 10 3 H 30")');
|
||||
assert_equals(getComputedStyle(p4).d, 'path("M 10 4 H 40")');
|
||||
assert_equals(getComputedStyle(g5).d, 'path("M 10 5 H 50")');
|
||||
assert_equals(getComputedStyle(p6).d, 'path("M 10 5 H 50")');
|
||||
assert_equals(getComputedStyle(p7).d, 'none');
|
||||
});
|
||||
]]></script>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
|
@ -1,6 +1,8 @@
|
|||
#!/bin/bash
|
||||
set -ex
|
||||
|
||||
./wpt manifest-download
|
||||
# This is allowed to fail
|
||||
./wpt manifest-download || echo
|
||||
|
||||
if [ $1 == "firefox" ]; then
|
||||
./wpt run firefox --log-tbpl=../artifacts/log_tbpl.log --log-tbpl-level=info --log-wptreport=../artifacts/wpt_report.json --log-mach=- --this-chunk=$4 --total-chunks=$5 --test-type=$3 -y --install-browser --channel=$2 --no-pause --no-restart-on-unexpected --reftest-internal --install-fonts --no-fail-on-unexpected
|
||||
|
|
|
@ -18,14 +18,14 @@ test_infrastructure() {
|
|||
}
|
||||
|
||||
main() {
|
||||
PRODUCTS=( "firefox" "chrome" )
|
||||
PRODUCTS=( "firefox" "chrome" "chrome_webdriver" )
|
||||
for PRODUCT in "${PRODUCTS[@]}"; do
|
||||
if [ "$PRODUCT" != "firefox" ]; then
|
||||
# Firefox is expected to work using pref settings for DNS
|
||||
# Don't adjust the hostnames in that case to ensure this keeps working
|
||||
hosts_fixup
|
||||
fi
|
||||
if [ "$PRODUCT" == "chrome" ]; then
|
||||
if [[ "$PRODUCT" == "chrome"* ]]; then
|
||||
install_chrome unstable
|
||||
test_infrastructure "--binary=$(which google-chrome-unstable)"
|
||||
else
|
||||
|
|
|
@ -6,8 +6,10 @@ class WebDriverException(Exception):
|
|||
http_status = None
|
||||
status_code = None
|
||||
|
||||
def __init__(self, message=None, stacktrace=None):
|
||||
def __init__(self, http_status=None, status_code=None, message=None, stacktrace=None):
|
||||
super(WebDriverException, self)
|
||||
self.http_status = http_status
|
||||
self.status_code = status_code
|
||||
self.message = message
|
||||
self.stacktrace = stacktrace
|
||||
|
||||
|
@ -171,6 +173,8 @@ def from_response(response):
|
|||
"""
|
||||
if response.status == 200:
|
||||
raise UnknownErrorException(
|
||||
response.status,
|
||||
None,
|
||||
"Response is not an error:\n"
|
||||
"%s" % json.dumps(response.body))
|
||||
|
||||
|
@ -178,6 +182,8 @@ def from_response(response):
|
|||
value = response.body["value"]
|
||||
else:
|
||||
raise UnknownErrorException(
|
||||
response.status,
|
||||
None,
|
||||
"Expected 'value' key in response body:\n"
|
||||
"%s" % json.dumps(response.body))
|
||||
|
||||
|
@ -187,7 +193,7 @@ def from_response(response):
|
|||
stack = value["stacktrace"] or None
|
||||
|
||||
cls = get(code)
|
||||
return cls(message, stacktrace=stack)
|
||||
return cls(response.status, code, message, stacktrace=stack)
|
||||
|
||||
|
||||
def get(error_code):
|
||||
|
|
|
@ -486,6 +486,12 @@ class ChromeAndroid(Browser):
|
|||
def version(self, binary):
|
||||
return None
|
||||
|
||||
class ChromeWebDriver(Chrome):
|
||||
"""Chrome-specific interface for chrome without using selenium.
|
||||
|
||||
Includes webdriver installation.
|
||||
"""
|
||||
product = "chrome_webdriver"
|
||||
|
||||
class Opera(Browser):
|
||||
"""Opera-specific interface.
|
||||
|
@ -582,6 +588,10 @@ class Edge(Browser):
|
|||
return None
|
||||
|
||||
|
||||
class EdgeWebDriver(Edge):
|
||||
product = "edge_webdriver"
|
||||
|
||||
|
||||
class InternetExplorer(Browser):
|
||||
"""Internet Explorer-specific interface."""
|
||||
|
||||
|
@ -629,6 +639,10 @@ class Safari(Browser):
|
|||
return None
|
||||
|
||||
|
||||
class SafariWebDriver(Safari):
|
||||
product = "safari_webdriver"
|
||||
|
||||
|
||||
class Servo(Browser):
|
||||
"""Servo-specific interface."""
|
||||
|
||||
|
|
|
@ -273,6 +273,10 @@ class ChromeAndroid(BrowserSetup):
|
|||
else:
|
||||
raise WptrunError("Unable to locate or install chromedriver binary")
|
||||
|
||||
class ChromeWebDriver(Chrome):
|
||||
name = "chrome_webdriver"
|
||||
browser_cls = browser.ChromeWebDriver
|
||||
|
||||
|
||||
class Opera(BrowserSetup):
|
||||
name = "opera"
|
||||
|
@ -318,6 +322,11 @@ https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
|
|||
kwargs["webdriver_binary"] = webdriver_binary
|
||||
|
||||
|
||||
class EdgeWebDriver(Edge):
|
||||
name = "edge_webdriver"
|
||||
browser_cls = browser.EdgeWebDriver
|
||||
|
||||
|
||||
class InternetExplorer(BrowserSetup):
|
||||
name = "ie"
|
||||
browser_cls = browser.InternetExplorer
|
||||
|
@ -356,6 +365,11 @@ class Safari(BrowserSetup):
|
|||
kwargs["webdriver_binary"] = webdriver_binary
|
||||
|
||||
|
||||
class SafariWebDriver(Safari):
|
||||
name = "safari_webdriver"
|
||||
browser_cls = browser.SafariWebDriver
|
||||
|
||||
|
||||
class Sauce(BrowserSetup):
|
||||
name = "sauce"
|
||||
browser_cls = browser.Sauce
|
||||
|
@ -402,9 +416,12 @@ product_setup = {
|
|||
"firefox": Firefox,
|
||||
"chrome": Chrome,
|
||||
"chrome_android": ChromeAndroid,
|
||||
"chrome_webdriver": ChromeWebDriver,
|
||||
"edge": Edge,
|
||||
"edge_webdriver": EdgeWebDriver,
|
||||
"ie": InternetExplorer,
|
||||
"safari": Safari,
|
||||
"safari_webdriver": SafariWebDriver,
|
||||
"servo": Servo,
|
||||
"sauce": Sauce,
|
||||
"opera": Opera,
|
||||
|
|
|
@ -101,9 +101,6 @@ def main(prog=None, argv=None):
|
|||
|
||||
main_args, command_args = parse_args(argv, commands)
|
||||
|
||||
if not(len(argv) and argv[0] in commands):
|
||||
sys.exit(1)
|
||||
|
||||
command = main_args.command
|
||||
props = commands[command]
|
||||
venv = None
|
||||
|
|
|
@ -24,11 +24,14 @@ module global scope.
|
|||
|
||||
product_list = ["chrome",
|
||||
"chrome_android",
|
||||
"chrome_webdriver",
|
||||
"edge",
|
||||
"edge_webdriver",
|
||||
"fennec",
|
||||
"firefox",
|
||||
"ie",
|
||||
"safari",
|
||||
"safari_webdriver",
|
||||
"sauce",
|
||||
"servo",
|
||||
"servodriver",
|
||||
|
|
|
@ -2,12 +2,32 @@ import os
|
|||
import platform
|
||||
import socket
|
||||
from abc import ABCMeta, abstractmethod
|
||||
from copy import deepcopy
|
||||
|
||||
from ..wptcommandline import require_arg # noqa: F401
|
||||
|
||||
here = os.path.split(__file__)[0]
|
||||
|
||||
|
||||
def inherit(super_module, child_globals, product_name):
|
||||
super_wptrunner = super_module.__wptrunner__
|
||||
child_globals["__wptrunner__"] = child_wptrunner = deepcopy(super_wptrunner)
|
||||
|
||||
child_wptrunner["product"] = product_name
|
||||
|
||||
for k in ("check_args", "browser", "browser_kwargs", "executor_kwargs",
|
||||
"env_extras", "env_options"):
|
||||
attr = super_wptrunner[k]
|
||||
child_globals[attr] = getattr(super_module, attr)
|
||||
|
||||
for v in super_module.__wptrunner__["executor"].values():
|
||||
child_globals[v] = getattr(super_module, v)
|
||||
|
||||
if "run_info_extras" in super_wptrunner:
|
||||
attr = super_wptrunner["run_info_extras"]
|
||||
child_globals[attr] = getattr(super_module, attr)
|
||||
|
||||
|
||||
def cmd_arg(name, value=None):
|
||||
prefix = "-" if platform.system() == "Windows" else "--"
|
||||
rv = prefix + name
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
from .base import inherit
|
||||
from . import chrome
|
||||
|
||||
from ..executors import executor_kwargs as base_executor_kwargs
|
||||
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
|
||||
WebDriverRefTestExecutor) # noqa: F401
|
||||
|
||||
|
||||
inherit(chrome, globals(), "chrome_webdriver")
|
||||
|
||||
# __wptrunner__ magically appears from inherit, F821 is undefined name
|
||||
__wptrunner__["executor_kwargs"] = "executor_kwargs" # noqa: F821
|
||||
__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821
|
||||
__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821
|
||||
|
||||
|
||||
def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
|
||||
**kwargs):
|
||||
executor_kwargs = base_executor_kwargs(test_type, server_config,
|
||||
cache_manager, run_info_data,
|
||||
**kwargs)
|
||||
executor_kwargs["close_after_done"] = True
|
||||
|
||||
capabilities = {
|
||||
"browserName": "chrome",
|
||||
"platform": "ANY",
|
||||
"version": "",
|
||||
"goog:chromeOptions": {
|
||||
"prefs": {
|
||||
"profile": {
|
||||
"default_content_setting_values": {
|
||||
"popups": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"w3c": True
|
||||
}
|
||||
}
|
||||
|
||||
for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]:
|
||||
if kwargs[kwarg] is not None:
|
||||
capabilities["goog:chromeOptions"][capability] = kwargs[kwarg]
|
||||
|
||||
if test_type == "testharness":
|
||||
capabilities["goog:chromeOptions"]["useAutomationExtension"] = False
|
||||
capabilities["goog:chromeOptions"]["excludeSwitches"] = ["enable-automation"]
|
||||
|
||||
executor_kwargs["capabilities"] = capabilities
|
||||
|
||||
return executor_kwargs
|
|
@ -0,0 +1,12 @@
|
|||
from .base import inherit
|
||||
from . import edge
|
||||
|
||||
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
|
||||
WebDriverRefTestExecutor) # noqa: F401
|
||||
|
||||
|
||||
inherit(edge, globals(), "edge_webdriver")
|
||||
|
||||
# __wptrunner__ magically appears from inherit, F821 is undefined name
|
||||
__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821
|
||||
__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821
|
|
@ -0,0 +1,12 @@
|
|||
from .base import inherit
|
||||
from . import safari
|
||||
|
||||
from ..executors.executorwebdriver import (WebDriverTestharnessExecutor, # noqa: F401
|
||||
WebDriverRefTestExecutor) # noqa: F401
|
||||
|
||||
|
||||
inherit(safari, globals(), "safari_webdriver")
|
||||
|
||||
# __wptrunner__ magically appears from inherit, F821 is undefined name
|
||||
__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor" # noqa: F821
|
||||
__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor" # noqa: F821
|
|
@ -95,14 +95,14 @@ class SeleniumTestharnessProtocolPart(TestharnessProtocolPart):
|
|||
|
||||
def get_test_window(self, window_id, parent):
|
||||
test_window = None
|
||||
if window_id:
|
||||
try:
|
||||
# Try this, it's in Level 1 but nothing supports it yet
|
||||
win_s = self.webdriver.execute_script("return window['%s'];" % self.window_id)
|
||||
win_obj = json.loads(win_s)
|
||||
test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
|
||||
except Exception:
|
||||
pass
|
||||
try:
|
||||
# Try using the JSON serialization of the WindowProxy object,
|
||||
# it's in Level 1 but nothing supports it yet
|
||||
win_s = self.webdriver.execute_script("return window['%s'];" % window_id)
|
||||
win_obj = json.loads(win_s)
|
||||
test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if test_window is None:
|
||||
after = self.webdriver.window_handles
|
||||
|
@ -296,7 +296,7 @@ class SeleniumTestharnessExecutor(TestharnessExecutor):
|
|||
parent_window = protocol.testharness.close_old_windows()
|
||||
# Now start the test harness
|
||||
protocol.base.execute_script(self.script % format_map)
|
||||
test_window = protocol.testharness.get_test_window(webdriver, parent_window)
|
||||
test_window = protocol.testharness.get_test_window(self.window_id, parent_window)
|
||||
|
||||
handler = CallbackHandler(self.logger, protocol, test_window)
|
||||
while True:
|
||||
|
|
|
@ -0,0 +1,373 @@
|
|||
import json
|
||||
import os
|
||||
import socket
|
||||
import threading
|
||||
import traceback
|
||||
import urlparse
|
||||
import uuid
|
||||
|
||||
from .base import (CallbackHandler,
|
||||
RefTestExecutor,
|
||||
RefTestImplementation,
|
||||
TestharnessExecutor,
|
||||
extra_timeout,
|
||||
strip_server)
|
||||
from .protocol import (BaseProtocolPart,
|
||||
TestharnessProtocolPart,
|
||||
Protocol,
|
||||
SelectorProtocolPart,
|
||||
ClickProtocolPart,
|
||||
SendKeysProtocolPart,
|
||||
TestDriverProtocolPart)
|
||||
from ..testrunner import Stop
|
||||
|
||||
import webdriver as client
|
||||
|
||||
here = os.path.join(os.path.split(__file__)[0])
|
||||
|
||||
class WebDriverBaseProtocolPart(BaseProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def execute_script(self, script, async=False):
|
||||
method = self.webdriver.execute_async_script if async else self.webdriver.execute_script
|
||||
return method(script)
|
||||
|
||||
def set_timeout(self, timeout):
|
||||
try:
|
||||
self.webdriver.timeouts.script = timeout
|
||||
except client.WebDriverException:
|
||||
# workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2057
|
||||
body = {"type": "script", "ms": timeout * 1000}
|
||||
self.webdriver.send_session_command("POST", "timeouts", body)
|
||||
|
||||
@property
|
||||
def current_window(self):
|
||||
return self.webdriver.window_handle
|
||||
|
||||
def set_window(self, handle):
|
||||
self.webdriver.window_handle = handle
|
||||
|
||||
def wait(self):
|
||||
while True:
|
||||
try:
|
||||
self.webdriver.execute_async_script("")
|
||||
except client.TimeoutException:
|
||||
pass
|
||||
except (socket.timeout, client.NoSuchWindowException,
|
||||
client.UnknownErrorException, IOError):
|
||||
break
|
||||
except Exception as e:
|
||||
self.logger.error(traceback.format_exc(e))
|
||||
break
|
||||
|
||||
|
||||
class WebDriverTestharnessProtocolPart(TestharnessProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def load_runner(self, url_protocol):
|
||||
url = urlparse.urljoin(self.parent.executor.server_url(url_protocol),
|
||||
"/testharness_runner.html")
|
||||
self.logger.debug("Loading %s" % url)
|
||||
|
||||
self.webdriver.url = url
|
||||
self.webdriver.execute_script("document.title = '%s'" %
|
||||
threading.current_thread().name.replace("'", '"'))
|
||||
|
||||
def close_old_windows(self):
|
||||
exclude = self.webdriver.window_handle
|
||||
handles = [item for item in self.webdriver.handles if item != exclude]
|
||||
for handle in handles:
|
||||
try:
|
||||
self.webdriver.window_handle = handle
|
||||
self.webdriver.close()
|
||||
except client.NoSuchWindowException:
|
||||
pass
|
||||
self.webdriver.window_handle = exclude
|
||||
return exclude
|
||||
|
||||
def get_test_window(self, window_id, parent):
|
||||
test_window = None
|
||||
try:
|
||||
# Try using the JSON serialization of the WindowProxy object,
|
||||
# it's in Level 1 but nothing supports it yet
|
||||
win_s = self.webdriver.execute_script("return window['%s'];" % window_id)
|
||||
win_obj = json.loads(win_s)
|
||||
test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if test_window is None:
|
||||
after = self.webdriver.handles
|
||||
if len(after) == 2:
|
||||
test_window = next(iter(set(after) - set([parent])))
|
||||
elif after[0] == parent and len(after) > 2:
|
||||
# Hope the first one here is the test window
|
||||
test_window = after[1]
|
||||
else:
|
||||
raise Exception("unable to find test window")
|
||||
|
||||
assert test_window != parent
|
||||
return test_window
|
||||
|
||||
|
||||
class WebDriverSelectorProtocolPart(SelectorProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def elements_by_selector(self, selector):
|
||||
return self.webdriver.find.css(selector)
|
||||
|
||||
|
||||
class WebDriverClickProtocolPart(ClickProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def element(self, element):
|
||||
return element.click()
|
||||
|
||||
|
||||
class WebDriverSendKeysProtocolPart(SendKeysProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def send_keys(self, element, keys):
|
||||
try:
|
||||
return element.send_keys(keys)
|
||||
except client.UnknownErrorException as e:
|
||||
# workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=1999
|
||||
if (e.http_status != 500 or
|
||||
e.status_code != "unknown error"):
|
||||
raise
|
||||
return element.send_element_command("POST", "value", {"value": list(keys)})
|
||||
|
||||
|
||||
class WebDriverTestDriverProtocolPart(TestDriverProtocolPart):
|
||||
def setup(self):
|
||||
self.webdriver = self.parent.webdriver
|
||||
|
||||
def send_message(self, message_type, status, message=None):
|
||||
obj = {
|
||||
"type": "testdriver-%s" % str(message_type),
|
||||
"status": str(status)
|
||||
}
|
||||
if message:
|
||||
obj["message"] = str(message)
|
||||
self.webdriver.execute_script("window.postMessage(%s, '*')" % json.dumps(obj))
|
||||
|
||||
|
||||
class WebDriverProtocol(Protocol):
|
||||
implements = [WebDriverBaseProtocolPart,
|
||||
WebDriverTestharnessProtocolPart,
|
||||
WebDriverSelectorProtocolPart,
|
||||
WebDriverClickProtocolPart,
|
||||
WebDriverSendKeysProtocolPart,
|
||||
WebDriverTestDriverProtocolPart]
|
||||
|
||||
def __init__(self, executor, browser, capabilities, **kwargs):
|
||||
super(WebDriverProtocol, self).__init__(executor, browser)
|
||||
self.capabilities = capabilities
|
||||
self.url = browser.webdriver_url
|
||||
self.webdriver = None
|
||||
|
||||
def connect(self):
|
||||
"""Connect to browser via WebDriver."""
|
||||
self.logger.debug("Connecting to WebDriver on URL: %s" % self.url)
|
||||
|
||||
host, port = self.url.split(":")[1].strip("/"), self.url.split(':')[-1].strip("/")
|
||||
|
||||
capabilities = {"alwaysMatch": self.capabilities}
|
||||
self.webdriver = client.Session(host, port, capabilities=capabilities)
|
||||
self.webdriver.start()
|
||||
|
||||
|
||||
def after_conect(self):
|
||||
pass
|
||||
|
||||
def teardown(self):
|
||||
self.logger.debug("Hanging up on WebDriver session")
|
||||
try:
|
||||
self.webdriver.quit()
|
||||
except Exception:
|
||||
pass
|
||||
del self.webdriver
|
||||
|
||||
def is_alive(self):
|
||||
try:
|
||||
# Get a simple property over the connection
|
||||
self.webdriver.window_handle
|
||||
except (socket.timeout, client.UnknownErrorException):
|
||||
return False
|
||||
return True
|
||||
|
||||
def after_connect(self):
|
||||
self.testharness.load_runner(self.executor.last_environment["protocol"])
|
||||
|
||||
|
||||
class WebDriverRun(object):
|
||||
def __init__(self, func, protocol, url, timeout):
|
||||
self.func = func
|
||||
self.result = None
|
||||
self.protocol = protocol
|
||||
self.url = url
|
||||
self.timeout = timeout
|
||||
self.result_flag = threading.Event()
|
||||
|
||||
def run(self):
|
||||
timeout = self.timeout
|
||||
|
||||
try:
|
||||
self.protocol.base.set_timeout((timeout + extra_timeout))
|
||||
except client.UnknownErrorException:
|
||||
self.logger.error("Lost WebDriver connection")
|
||||
return Stop
|
||||
|
||||
executor = threading.Thread(target=self._run)
|
||||
executor.start()
|
||||
|
||||
flag = self.result_flag.wait(timeout + 2 * extra_timeout)
|
||||
if self.result is None:
|
||||
assert not flag
|
||||
self.result = False, ("EXTERNAL-TIMEOUT", None)
|
||||
|
||||
return self.result
|
||||
|
||||
def _run(self):
|
||||
try:
|
||||
self.result = True, self.func(self.protocol, self.url, self.timeout)
|
||||
except client.TimeoutException:
|
||||
self.result = False, ("EXTERNAL-TIMEOUT", None)
|
||||
except (socket.timeout, client.UnknownErrorException):
|
||||
self.result = False, ("CRASH", None)
|
||||
except Exception as e:
|
||||
if (isinstance(e, client.WebDriverException) and
|
||||
e.http_status == 408 and
|
||||
e.status_code == "asynchronous script timeout"):
|
||||
# workaround for https://bugs.chromium.org/p/chromedriver/issues/detail?id=2001
|
||||
self.result = False, ("EXTERNAL-TIMEOUT", None)
|
||||
else:
|
||||
message = getattr(e, "message", "")
|
||||
if message:
|
||||
message += "\n"
|
||||
message += traceback.format_exc(e)
|
||||
self.result = False, ("ERROR", message)
|
||||
finally:
|
||||
self.result_flag.set()
|
||||
|
||||
|
||||
class WebDriverTestharnessExecutor(TestharnessExecutor):
|
||||
supports_testdriver = True
|
||||
|
||||
def __init__(self, browser, server_config, timeout_multiplier=1,
|
||||
close_after_done=True, capabilities=None, debug_info=None,
|
||||
**kwargs):
|
||||
"""WebDriver-based executor for testharness.js tests"""
|
||||
TestharnessExecutor.__init__(self, browser, server_config,
|
||||
timeout_multiplier=timeout_multiplier,
|
||||
debug_info=debug_info)
|
||||
self.protocol = WebDriverProtocol(self, browser, capabilities)
|
||||
with open(os.path.join(here, "testharness_webdriver.js")) as f:
|
||||
self.script = f.read()
|
||||
with open(os.path.join(here, "testharness_webdriver_resume.js")) as f:
|
||||
self.script_resume = f.read()
|
||||
self.close_after_done = close_after_done
|
||||
self.window_id = str(uuid.uuid4())
|
||||
|
||||
def is_alive(self):
|
||||
return self.protocol.is_alive()
|
||||
|
||||
def on_environment_change(self, new_environment):
|
||||
if new_environment["protocol"] != self.last_environment["protocol"]:
|
||||
self.protocol.testharness.load_runner(new_environment["protocol"])
|
||||
|
||||
def do_test(self, test):
|
||||
url = self.test_url(test)
|
||||
|
||||
success, data = WebDriverRun(self.do_testharness,
|
||||
self.protocol,
|
||||
url,
|
||||
test.timeout * self.timeout_multiplier).run()
|
||||
|
||||
if success:
|
||||
return self.convert_result(test, data)
|
||||
|
||||
return (test.result_cls(*data), [])
|
||||
|
||||
def do_testharness(self, protocol, url, timeout):
|
||||
format_map = {"abs_url": url,
|
||||
"url": strip_server(url),
|
||||
"window_id": self.window_id,
|
||||
"timeout_multiplier": self.timeout_multiplier,
|
||||
"timeout": timeout * 1000}
|
||||
|
||||
parent_window = protocol.testharness.close_old_windows()
|
||||
# Now start the test harness
|
||||
protocol.base.execute_script(self.script % format_map)
|
||||
test_window = protocol.testharness.get_test_window(self.window_id, parent_window)
|
||||
|
||||
handler = CallbackHandler(self.logger, protocol, test_window)
|
||||
while True:
|
||||
result = protocol.base.execute_script(
|
||||
self.script_resume % format_map, async=True)
|
||||
done, rv = handler(result)
|
||||
if done:
|
||||
break
|
||||
return rv
|
||||
|
||||
|
||||
class WebDriverRefTestExecutor(RefTestExecutor):
|
||||
def __init__(self, browser, server_config, timeout_multiplier=1,
|
||||
screenshot_cache=None, close_after_done=True,
|
||||
debug_info=None, capabilities=None, **kwargs):
|
||||
"""WebDriver-based executor for reftests"""
|
||||
RefTestExecutor.__init__(self,
|
||||
browser,
|
||||
server_config,
|
||||
screenshot_cache=screenshot_cache,
|
||||
timeout_multiplier=timeout_multiplier,
|
||||
debug_info=debug_info)
|
||||
self.protocol = WebDriverProtocol(self, browser,
|
||||
capabilities=capabilities)
|
||||
self.implementation = RefTestImplementation(self)
|
||||
self.close_after_done = close_after_done
|
||||
self.has_window = False
|
||||
|
||||
with open(os.path.join(here, "reftest.js")) as f:
|
||||
self.script = f.read()
|
||||
with open(os.path.join(here, "reftest-wait_webdriver.js")) as f:
|
||||
self.wait_script = f.read()
|
||||
|
||||
def is_alive(self):
|
||||
return self.protocol.is_alive()
|
||||
|
||||
def do_test(self, test):
|
||||
self.protocol.webdriver.window.size = (600, 600)
|
||||
|
||||
result = self.implementation.run_test(test)
|
||||
|
||||
return self.convert_result(test, result)
|
||||
|
||||
def screenshot(self, test, viewport_size, dpi):
|
||||
# https://github.com/w3c/wptrunner/issues/166
|
||||
assert viewport_size is None
|
||||
assert dpi is None
|
||||
|
||||
return WebDriverRun(self._screenshot,
|
||||
self.protocol,
|
||||
self.test_url(test),
|
||||
test.timeout).run()
|
||||
|
||||
def _screenshot(self, protocol, url, timeout):
|
||||
webdriver = protocol.webdriver
|
||||
webdriver.url = url
|
||||
|
||||
webdriver.execute_async_script(self.wait_script)
|
||||
|
||||
screenshot = webdriver.screenshot()
|
||||
|
||||
# strip off the data:img/png, part of the url
|
||||
if screenshot.startswith("data:image/png;base64,"):
|
||||
screenshot = screenshot.split(",", 1)[1]
|
||||
|
||||
return screenshot
|
|
@ -96,8 +96,12 @@ class LogHandler(reader.LogHandler):
|
|||
duration = data["time"] - test.pop("start_time")
|
||||
test["longest_duration"][data["status"]] = max(
|
||||
duration, test["longest_duration"][data["status"]])
|
||||
# test_timeout is in seconds; convert it to ms.
|
||||
test["timeout"] = data["extra"]["test_timeout"] * 1000
|
||||
try:
|
||||
# test_timeout is in seconds; convert it to ms.
|
||||
test["timeout"] = data["extra"]["test_timeout"] * 1000
|
||||
except KeyError:
|
||||
# If a test is skipped, it won't have extra info.
|
||||
pass
|
||||
|
||||
|
||||
def is_inconsistent(results_dict, iterations):
|
||||
|
@ -118,6 +122,8 @@ def find_slow_status(test):
|
|||
A result status produced by a run that almost times out; None, if no
|
||||
runs almost time out.
|
||||
"""
|
||||
if "timeout" not in test:
|
||||
return None
|
||||
threshold = test["timeout"] * FLAKY_THRESHOLD
|
||||
for status in ['PASS', 'FAIL', 'OK', 'ERROR']:
|
||||
if (status in test["longest_duration"] and
|
||||
|
|
|
@ -17,7 +17,9 @@ if "CURRENT_TOX_ENV" in os.environ:
|
|||
current_tox_env_split = os.environ["CURRENT_TOX_ENV"].split("-")
|
||||
|
||||
tox_env_extra_browsers = {
|
||||
"chrome": {"chrome_android"},
|
||||
"chrome": {"chrome_android", "chrome_webdriver"},
|
||||
"edge": {"edge_webdriver"},
|
||||
"safari": {"safari_webdriver"},
|
||||
"servo": {"servodriver"},
|
||||
}
|
||||
|
||||
|
|
|
@ -29,3 +29,5 @@ def test_find_slow_status():
|
|||
assert stability.find_slow_status({
|
||||
"longest_duration": {"TIMEOUT": 10, "FAIL": 81},
|
||||
"timeout": 100}) == "FAIL"
|
||||
assert stability.find_slow_status({
|
||||
"longest_duration": {"SKIP": 0}}) is None
|
||||
|
|
|
@ -96,11 +96,38 @@ class UpdateMetadata(Step):
|
|||
runner.run()
|
||||
|
||||
|
||||
class RemoveObsolete(Step):
|
||||
"""Remove metadata files that don't corespond to an existing test file"""
|
||||
|
||||
def create(self, state):
|
||||
if not state.kwargs["remove_obsolete"]:
|
||||
return
|
||||
|
||||
paths = state.kwargs["test_paths"]
|
||||
state.tests_path = state.paths["/"]["tests_path"]
|
||||
state.metadata_path = state.paths["/"]["metadata_path"]
|
||||
|
||||
for url_paths in paths.itervalues():
|
||||
tests_path = url_paths["tests_path"]
|
||||
metadata_path = url_paths["metadata_path"]
|
||||
for dirpath, dirnames, filenames in os.walk(metadata_path):
|
||||
for filename in filenames:
|
||||
if filename == "__dir__.ini":
|
||||
continue
|
||||
if filename.endswith(".ini"):
|
||||
full_path = os.path.join(dirpath, filename)
|
||||
rel_path = os.path.relpath(full_path, metadata_path)
|
||||
test_path = os.path.join(tests_path, rel_path[:-4])
|
||||
if not os.path.exists(test_path):
|
||||
os.unlink(full_path)
|
||||
|
||||
|
||||
class UpdateRunner(StepRunner):
|
||||
"""Runner for doing an overall update."""
|
||||
steps = [LoadConfig,
|
||||
LoadTrees,
|
||||
SyncFromUpstream,
|
||||
RemoveObsolete,
|
||||
UpdateMetadata]
|
||||
|
||||
|
||||
|
|
|
@ -565,8 +565,14 @@ def create_parser_update(product_choices=None):
|
|||
parser.add_argument("--stability", nargs="?", action="store", const="unstable", default=None,
|
||||
help=("Reason for disabling tests. When updating test results, disable tests that have "
|
||||
"inconsistent results across many runs with the given reason."))
|
||||
parser.add_argument("--continue", action="store_true", help="Continue a previously started run of the update script")
|
||||
parser.add_argument("--abort", action="store_true", help="Clear state from a previous incomplete run of the update script")
|
||||
parser.add_argument("--no-remove-obsolete", action="store_false", dest="remove_obsolete", default=True,
|
||||
help=("Don't remove metadata files that no longer correspond to a test file"))
|
||||
parser.add_argument("--no-store-state", action="store_false", dest="store_state",
|
||||
help="Store state so that steps can be resumed after failure")
|
||||
parser.add_argument("--continue", action="store_true",
|
||||
help="Continue a previously started run of the update script")
|
||||
parser.add_argument("--abort", action="store_true",
|
||||
help="Clear state from a previous incomplete run of the update script")
|
||||
parser.add_argument("--exclude", action="store", nargs="*",
|
||||
help="List of glob-style paths to exclude when syncing tests")
|
||||
parser.add_argument("--include", action="store", nargs="*",
|
||||
|
|
|
@ -15,3 +15,59 @@ function assert_function_length(fn, length, description) {
|
|||
assert_true(propdesc.configurable, "configurable", `${description} length should be configurable`);
|
||||
assert_equals(propdesc.value, length, `${description} length should be ${length}`);
|
||||
}
|
||||
|
||||
function assert_exported_function(fn, { name, length }, description) {
|
||||
assert_equals(Object.getPrototypeOf(fn), Function.prototype,
|
||||
`${description}: prototype`);
|
||||
|
||||
assert_function_name(fn, name, description);
|
||||
assert_function_length(fn, length, description);
|
||||
}
|
||||
|
||||
function assert_Instance(instance, expected_exports) {
|
||||
assert_equals(Object.getPrototypeOf(instance), WebAssembly.Instance.prototype,
|
||||
"prototype");
|
||||
assert_true(Object.isExtensible(instance), "extensible");
|
||||
|
||||
assert_equals(instance.exports, instance.exports, "exports should be idempotent");
|
||||
const exports = instance.exports;
|
||||
|
||||
assert_equals(Object.getPrototypeOf(exports), null, "exports prototype");
|
||||
assert_false(Object.isExtensible(exports), "extensible exports");
|
||||
for (const [key, expected] of Object.entries(expected_exports)) {
|
||||
const property = Object.getOwnPropertyDescriptor(exports, key);
|
||||
assert_equals(typeof property, "object", `${key} should be present`);
|
||||
assert_false(property.writable, `${key}: writable`);
|
||||
assert_true(property.enumerable, `${key}: enumerable`);
|
||||
assert_false(property.configurable, `${key}: configurable`);
|
||||
const actual = property.value;
|
||||
assert_true(Object.isExtensible(actual), `${key}: extensible`);
|
||||
|
||||
switch (expected.kind) {
|
||||
case "function":
|
||||
assert_exported_function(actual, expected, `value of ${key}`);
|
||||
break;
|
||||
case "global":
|
||||
assert_equals(Object.getPrototypeOf(actual), WebAssembly.Global.prototype,
|
||||
`value of ${key}: prototype`);
|
||||
assert_equals(actual.value, expected.value, `value of ${key}: value`);
|
||||
assert_equals(actual.valueOf(), expected.value, `value of ${key}: valueOf()`);
|
||||
break;
|
||||
case "memory":
|
||||
assert_equals(Object.getPrototypeOf(actual), WebAssembly.Memory.prototype,
|
||||
`value of ${key}: prototype`);
|
||||
assert_equals(Object.getPrototypeOf(actual.buffer), ArrayBuffer.prototype,
|
||||
`value of ${key}: prototype of buffer`);
|
||||
assert_equals(actual.buffer.byteLength, 0x10000 * expected.size, `value of ${key}: size of buffer`);
|
||||
const array = new Uint8Array(actual.buffer);
|
||||
assert_equals(array[0], 0, `value of ${key}: first element of buffer`);
|
||||
assert_equals(array[array.byteLength - 1], 0, `value of ${key}: last element of buffer`);
|
||||
break;
|
||||
case "table":
|
||||
assert_equals(Object.getPrototypeOf(actual), WebAssembly.Table.prototype,
|
||||
`value of ${key}: prototype`);
|
||||
assert_equals(actual.length, expected.length, `value of ${key}: length of table`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
// META: global=jsshell
|
||||
// META: script=/wasm/jsapi/wasm-constants.js
|
||||
// META: script=/wasm/jsapi/wasm-module-builder.js
|
||||
|
||||
function assert_Module(module) {
|
||||
assert_equals(Object.getPrototypeOf(module), WebAssembly.Module.prototype,
|
||||
"Prototype");
|
||||
assert_true(Object.isExtensible(module), "Extensibility");
|
||||
}
|
||||
|
||||
let emptyModuleBinary;
|
||||
setup(() => {
|
||||
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
|
||||
});
|
||||
|
||||
promise_test(t => {
|
||||
return promise_rejects(t, new TypeError(), WebAssembly.compile());
|
||||
}, "Missing argument");
|
||||
|
||||
promise_test(t => {
|
||||
const invalidArguments = [
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
"",
|
||||
Symbol(),
|
||||
1,
|
||||
{},
|
||||
ArrayBuffer,
|
||||
ArrayBuffer.prototype,
|
||||
Array.from(emptyModuleBinary),
|
||||
];
|
||||
return Promise.all(invalidArguments.map(argument => {
|
||||
return promise_rejects(t, new TypeError(), WebAssembly.compile(argument),
|
||||
`compile(${format_value(argument)})`);
|
||||
}));
|
||||
}, "Invalid arguments");
|
||||
|
||||
promise_test(() => {
|
||||
const fn = WebAssembly.compile;
|
||||
const thisValues = [
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
"",
|
||||
Symbol(),
|
||||
1,
|
||||
{},
|
||||
WebAssembly,
|
||||
];
|
||||
return Promise.all(thisValues.map(thisValue => {
|
||||
return fn.call(thisValue, emptyModuleBinary).then(assert_Module);
|
||||
}));
|
||||
}, "Branding");
|
||||
|
||||
test(() => {
|
||||
const promise = WebAssembly.compile(emptyModuleBinary);
|
||||
assert_equals(Object.getPrototypeOf(promise), Promise.prototype, "prototype");
|
||||
assert_true(Object.isExtensible(promise), "extensibility");
|
||||
}, "Promise type");
|
||||
|
||||
promise_test(t => {
|
||||
const buffer = new Uint8Array();
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.compile(buffer));
|
||||
}, "Invalid code");
|
||||
|
||||
promise_test(() => {
|
||||
return WebAssembly.compile(emptyModuleBinary).then(assert_Module);
|
||||
}, "Result type");
|
||||
|
||||
promise_test(() => {
|
||||
const buffer = new WasmModuleBuilder().toBuffer();
|
||||
assert_equals(buffer[0], 0);
|
||||
const promise = WebAssembly.compile(buffer);
|
||||
buffer[0] = 1;
|
||||
return promise.then(assert_Module);
|
||||
}, "Changing the buffer");
|
|
@ -0,0 +1,196 @@
|
|||
// META: global=jsshell
|
||||
// META: script=/wasm/jsapi/wasm-constants.js
|
||||
// META: script=/wasm/jsapi/wasm-module-builder.js
|
||||
// META: script=/wasm/jsapi/assertions.js
|
||||
|
||||
function assert_WebAssemblyInstantiatedSource(actual, expected_exports={}) {
|
||||
assert_equals(Object.getPrototypeOf(actual), Object.prototype,
|
||||
"Prototype");
|
||||
assert_true(Object.isExtensible(actual), "Extensibility");
|
||||
|
||||
const module = Object.getOwnPropertyDescriptor(actual, "module");
|
||||
assert_equals(typeof module, "object", "module: type of descriptor");
|
||||
assert_true(module.writable, "module: writable");
|
||||
assert_true(module.enumerable, "module: enumerable");
|
||||
assert_true(module.configurable, "module: configurable");
|
||||
assert_equals(Object.getPrototypeOf(module.value), WebAssembly.Module.prototype,
|
||||
"module: prototype");
|
||||
|
||||
const instance = Object.getOwnPropertyDescriptor(actual, "instance");
|
||||
assert_equals(typeof instance, "object", "instance: type of descriptor");
|
||||
assert_true(instance.writable, "instance: writable");
|
||||
assert_true(instance.enumerable, "instance: enumerable");
|
||||
assert_true(instance.configurable, "instance: configurable");
|
||||
assert_Instance(instance.value, expected_exports);
|
||||
}
|
||||
|
||||
let emptyModuleBinary;
|
||||
setup(() => {
|
||||
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
|
||||
});
|
||||
|
||||
promise_test(t => {
|
||||
return promise_rejects(t, new TypeError(), WebAssembly.instantiate());
|
||||
}, "Missing arguments");
|
||||
|
||||
promise_test(() => {
|
||||
const fn = WebAssembly.instantiate;
|
||||
const thisValues = [
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
"",
|
||||
Symbol(),
|
||||
1,
|
||||
{},
|
||||
WebAssembly,
|
||||
];
|
||||
return Promise.all(thisValues.map(thisValue => {
|
||||
return fn.call(thisValue, emptyModuleBinary).then(assert_WebAssemblyInstantiatedSource);
|
||||
}));
|
||||
}, "Branding");
|
||||
|
||||
promise_test(t => {
|
||||
const invalidArguments = [
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
"",
|
||||
Symbol(),
|
||||
1,
|
||||
{},
|
||||
WebAssembly.Module,
|
||||
WebAssembly.Module.prototype,
|
||||
ArrayBuffer,
|
||||
ArrayBuffer.prototype,
|
||||
Array.from(emptyModuleBinary),
|
||||
];
|
||||
return Promise.all(invalidArguments.map(argument => {
|
||||
return promise_rejects(t, new TypeError(), WebAssembly.instantiate(argument),
|
||||
`instantiate(${format_value(argument)})`);
|
||||
}));
|
||||
}, "Invalid arguments");
|
||||
|
||||
test(() => {
|
||||
const promise = WebAssembly.instantiate(emptyModuleBinary);
|
||||
assert_equals(Object.getPrototypeOf(promise), Promise.prototype, "prototype");
|
||||
assert_true(Object.isExtensible(promise), "extensibility");
|
||||
}, "Promise type");
|
||||
|
||||
const createModule = () => {
|
||||
const builder = new WasmModuleBuilder();
|
||||
|
||||
builder
|
||||
.addFunction("fn", kSig_v_d)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.exportFunc();
|
||||
builder
|
||||
.addFunction("fn2", kSig_v_v)
|
||||
.addBody([
|
||||
kExprEnd
|
||||
])
|
||||
.exportFunc();
|
||||
|
||||
builder.setFunctionTableLength(1);
|
||||
builder.addExportOfKind("table", kExternalTable, 0);
|
||||
|
||||
builder.addGlobal(kWasmI32, true)
|
||||
.exportAs("global")
|
||||
.init = 7;
|
||||
builder.addGlobal(kWasmF64, true)
|
||||
.exportAs("global2")
|
||||
.init = 1.2;
|
||||
|
||||
builder.addMemory(4, 8, true);
|
||||
|
||||
const buffer = builder.toBuffer();
|
||||
|
||||
const exports = {
|
||||
"fn": { "kind": "function", "name": "0", "length": 1 },
|
||||
"fn2": { "kind": "function", "name": "1", "length": 0 },
|
||||
"table": { "kind": "table", "length": 1 },
|
||||
"global": { "kind": "global", "value": 7 },
|
||||
"global2": { "kind": "global", "value": 1.2 },
|
||||
"memory": { "kind": "memory", "size": 4 },
|
||||
};
|
||||
|
||||
return [buffer, exports];
|
||||
}
|
||||
|
||||
promise_test(() => {
|
||||
const [buffer, expected] = createModule();
|
||||
return WebAssembly.instantiate(buffer).then(result => assert_WebAssemblyInstantiatedSource(result, expected));
|
||||
}, "BufferSource argument");
|
||||
|
||||
promise_test(() => {
|
||||
const [buffer, expected] = createModule();
|
||||
const module = new WebAssembly.Module(buffer);
|
||||
return WebAssembly.instantiate(module).then(instance => assert_Instance(instance, expected));
|
||||
}, "Module argument");
|
||||
|
||||
const createModuleWithImports = () => {
|
||||
const builder = new WasmModuleBuilder();
|
||||
|
||||
const index = builder.addImportedGlobal("module", "global", kWasmI32);
|
||||
builder
|
||||
.addFunction("fn", kSig_i_v)
|
||||
.addBody([
|
||||
kExprGetGlobal,
|
||||
index,
|
||||
kExprReturn,
|
||||
kExprEnd,
|
||||
])
|
||||
.exportFunc();
|
||||
|
||||
const buffer = builder.toBuffer();
|
||||
|
||||
const expected = {
|
||||
"fn": { "kind": "function", "name": "0", "length": 0 },
|
||||
};
|
||||
|
||||
return [buffer, expected];
|
||||
};
|
||||
|
||||
promise_test(() => {
|
||||
const [buffer, expected] = createModuleWithImports();
|
||||
|
||||
const value = 102;
|
||||
return WebAssembly.instantiate(buffer, {
|
||||
"module": {
|
||||
"global": value,
|
||||
},
|
||||
}).then(result => {
|
||||
assert_WebAssemblyInstantiatedSource(result, expected)
|
||||
assert_equals(result.instance.exports.fn(), value);
|
||||
});
|
||||
}, "exports and imports: buffer argument");
|
||||
|
||||
promise_test(() => {
|
||||
const [buffer, expected] = createModuleWithImports();
|
||||
const module = new WebAssembly.Module(buffer);
|
||||
|
||||
const value = 102;
|
||||
return WebAssembly.instantiate(module, {
|
||||
"module": {
|
||||
"global": value,
|
||||
},
|
||||
}).then(instance => {
|
||||
assert_Instance(instance, expected)
|
||||
assert_equals(instance.exports.fn(), value);
|
||||
});
|
||||
}, "exports and imports: Module argument");
|
||||
|
||||
promise_test(t => {
|
||||
const buffer = new Uint8Array();
|
||||
return promise_rejects(t, new WebAssembly.CompileError(), WebAssembly.instantiate(buffer));
|
||||
}, "Invalid code");
|
||||
|
||||
promise_test(() => {
|
||||
const buffer = new WasmModuleBuilder().toBuffer();
|
||||
assert_equals(buffer[0], 0);
|
||||
const promise = WebAssembly.instantiate(buffer);
|
||||
buffer[0] = 1;
|
||||
return promise.then(assert_WebAssemblyInstantiatedSource);
|
||||
}, "Changing the buffer");
|
|
@ -0,0 +1,96 @@
|
|||
// META: global=jsshell
|
||||
// META: script=/wasm/jsapi/wasm-constants.js
|
||||
// META: script=/wasm/jsapi/wasm-module-builder.js
|
||||
|
||||
let emptyModuleBinary;
|
||||
setup(() => {
|
||||
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
|
||||
});
|
||||
|
||||
test(() => {
|
||||
assert_throws(new TypeError(), () => WebAssembly.validate());
|
||||
}, "Missing argument");
|
||||
|
||||
test(() => {
|
||||
const invalidArguments = [
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
"",
|
||||
Symbol(),
|
||||
1,
|
||||
{},
|
||||
ArrayBuffer,
|
||||
ArrayBuffer.prototype,
|
||||
Array.from(emptyModuleBinary),
|
||||
];
|
||||
for (const argument of invalidArguments) {
|
||||
assert_throws(new TypeError(), () => WebAssembly.validate(argument),
|
||||
`validate(${format_value(argument)})`);
|
||||
}
|
||||
}, "Invalid arguments");
|
||||
|
||||
test(() => {
|
||||
const fn = WebAssembly.validate;
|
||||
const thisValues = [
|
||||
undefined,
|
||||
null,
|
||||
true,
|
||||
"",
|
||||
Symbol(),
|
||||
1,
|
||||
{},
|
||||
WebAssembly,
|
||||
];
|
||||
for (const thisValue of thisValues) {
|
||||
assert_true(fn.call(thisValue, emptyModuleBinary), `this=${format_value(thisValue)}`);
|
||||
}
|
||||
}, "Branding");
|
||||
|
||||
const modules = [
|
||||
// Incomplete header.
|
||||
[[], false],
|
||||
[[0x00], false],
|
||||
[[0x00, 0x61], false],
|
||||
[[0x00, 0x61, 0x73], false],
|
||||
[[0x00, 0x61, 0x73, 0x6d], false],
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x01], false],
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00], false],
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00], false],
|
||||
|
||||
// Complete header.
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00], true],
|
||||
|
||||
// Invalid version.
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x00, 0x00, 0x00, 0x00], false],
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x02, 0x00, 0x00, 0x00], false],
|
||||
|
||||
// Nameless custom section.
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00], false],
|
||||
|
||||
// Custom section with empty name.
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00], true],
|
||||
|
||||
// Custom section with name "a".
|
||||
[[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x61], true],
|
||||
];
|
||||
const bufferTypes = [
|
||||
Uint8Array,
|
||||
Int8Array,
|
||||
Uint16Array,
|
||||
Int16Array,
|
||||
Uint32Array,
|
||||
Int32Array,
|
||||
];
|
||||
for (const [module, expected] of modules) {
|
||||
const name = module.map(n => n.toString(16)).join(" ");
|
||||
for (const bufferType of bufferTypes) {
|
||||
if (module.length % bufferType.BYTES_PER_ELEMENT === 0) {
|
||||
test(() => {
|
||||
const bytes = new Uint8Array(module);
|
||||
const moduleBuffer = new bufferType(bytes.buffer);
|
||||
assert_equals(WebAssembly.validate(moduleBuffer), expected);
|
||||
}, `Validating module [${name}] in ${bufferType.name}`);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,62 +3,6 @@
|
|||
// META: script=/wasm/jsapi/wasm-module-builder.js
|
||||
// META: script=/wasm/jsapi/assertions.js
|
||||
|
||||
function assert_exported_function(fn, { name, length }, description) {
|
||||
assert_equals(Object.getPrototypeOf(fn), Function.prototype,
|
||||
`${description}: prototype`);
|
||||
|
||||
assert_function_name(fn, name, description);
|
||||
assert_function_length(fn, length, description);
|
||||
}
|
||||
|
||||
function assert_Instance(instance, expected_exports) {
|
||||
assert_equals(Object.getPrototypeOf(instance), WebAssembly.Instance.prototype,
|
||||
"prototype");
|
||||
assert_true(Object.isExtensible(instance), "extensible");
|
||||
|
||||
assert_equals(instance.exports, instance.exports, "exports should be idempotent");
|
||||
const exports = instance.exports;
|
||||
|
||||
assert_equals(Object.getPrototypeOf(exports), null, "exports prototype");
|
||||
assert_false(Object.isExtensible(exports), "extensible exports");
|
||||
for (const [key, expected] of Object.entries(expected_exports)) {
|
||||
const property = Object.getOwnPropertyDescriptor(exports, key);
|
||||
assert_equals(typeof property, "object", `${key} should be present`);
|
||||
assert_false(property.writable, `${key}: writable`);
|
||||
assert_true(property.enumerable, `${key}: enumerable`);
|
||||
assert_false(property.configurable, `${key}: configurable`);
|
||||
const actual = property.value;
|
||||
assert_true(Object.isExtensible(actual), `${key}: extensible`);
|
||||
|
||||
switch (expected.kind) {
|
||||
case "function":
|
||||
assert_exported_function(actual, expected, `value of ${key}`);
|
||||
break;
|
||||
case "global":
|
||||
assert_equals(Object.getPrototypeOf(actual), WebAssembly.Global.prototype,
|
||||
`value of ${key}: prototype`);
|
||||
assert_equals(actual.value, expected.value, `value of ${key}: value`);
|
||||
assert_equals(actual.valueOf(), expected.value, `value of ${key}: valueOf()`);
|
||||
break;
|
||||
case "memory":
|
||||
assert_equals(Object.getPrototypeOf(actual), WebAssembly.Memory.prototype,
|
||||
`value of ${key}: prototype`);
|
||||
assert_equals(Object.getPrototypeOf(actual.buffer), ArrayBuffer.prototype,
|
||||
`value of ${key}: prototype of buffer`);
|
||||
assert_equals(actual.buffer.byteLength, 0x10000 * expected.size, `value of ${key}: size of buffer`);
|
||||
const array = new Uint8Array(actual.buffer);
|
||||
assert_equals(array[0], 0, `value of ${key}: first element of buffer`);
|
||||
assert_equals(array[array.byteLength - 1], 0, `value of ${key}: last element of buffer`);
|
||||
break;
|
||||
case "table":
|
||||
assert_equals(Object.getPrototypeOf(actual), WebAssembly.Table.prototype,
|
||||
`value of ${key}: prototype`);
|
||||
assert_equals(actual.length, expected.length, `value of ${key}: length of table`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let emptyModuleBinary;
|
||||
setup(() => {
|
||||
emptyModuleBinary = new WasmModuleBuilder().toBuffer();
|
||||
|
@ -130,6 +74,8 @@ test(() => {
|
|||
test(() => {
|
||||
const builder = new WasmModuleBuilder();
|
||||
builder.addImportedGlobal("module", "global1", kWasmI32);
|
||||
builder.addImportedGlobal("module2", "global3", kWasmI32);
|
||||
builder.addImportedMemory("module", "memory", 0, 128);
|
||||
builder.addImportedGlobal("module", "global2", kWasmI32);
|
||||
const buffer = builder.toBuffer();
|
||||
const module = new WebAssembly.Module(buffer);
|
||||
|
@ -146,6 +92,19 @@ test(() => {
|
|||
order.push("global2 getter");
|
||||
return 0;
|
||||
},
|
||||
get memory() {
|
||||
order.push("memory getter");
|
||||
return new WebAssembly.Memory({ "initial": 64, maximum: 128 });
|
||||
},
|
||||
}
|
||||
},
|
||||
get module2() {
|
||||
order.push("module2 getter");
|
||||
return {
|
||||
get global3() {
|
||||
order.push("global3 getter");
|
||||
return 0;
|
||||
},
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -153,6 +112,10 @@ test(() => {
|
|||
const expected = [
|
||||
"module getter",
|
||||
"global1 getter",
|
||||
"module2 getter",
|
||||
"global3 getter",
|
||||
"module getter",
|
||||
"memory getter",
|
||||
"module getter",
|
||||
"global2 getter",
|
||||
];
|
||||
|
@ -225,3 +188,34 @@ test(() => {
|
|||
};
|
||||
assert_Instance(instance, expected);
|
||||
}, "exports");
|
||||
|
||||
test(() => {
|
||||
const value = 102;
|
||||
|
||||
const builder = new WasmModuleBuilder();
|
||||
|
||||
builder.addImportedGlobal("module", "global", kWasmI32);
|
||||
builder
|
||||
.addFunction("fn", kSig_i_v)
|
||||
.addBody([
|
||||
kExprGetGlobal,
|
||||
0,
|
||||
kExprReturn,
|
||||
kExprEnd,
|
||||
])
|
||||
.exportFunc();
|
||||
|
||||
const buffer = builder.toBuffer();
|
||||
const module = new WebAssembly.Module(buffer);
|
||||
const instance = new WebAssembly.Instance(module, {
|
||||
"module": {
|
||||
"global": value,
|
||||
},
|
||||
});
|
||||
const expected = {
|
||||
"fn": { "kind": "function", "name": "0", "length": 0 },
|
||||
};
|
||||
assert_Instance(instance, expected);
|
||||
|
||||
assert_equals(instance.exports.fn(), value);
|
||||
}, "exports and imports");
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test Extrapolation at end of AudibBuffer in an AudioBufferSourceNode</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/webaudio/resources/audit-util.js"></script>
|
||||
<script src="/webaudio/resources/audit.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
let audit = Audit.createTaskRunner();
|
||||
|
||||
const sampleRate = 48000;
|
||||
|
||||
// For testing we only need a few render quanta.
|
||||
const renderSamples = 512
|
||||
|
||||
// Sample rate for our buffers. This is the lowest sample rate that is
|
||||
// required to be supported.
|
||||
const bufferRate = 8000;
|
||||
|
||||
// Number of samples in each AudioBuffer; this is fairly arbitrary but
|
||||
// should be less than a render quantum.
|
||||
const bufferLength = 30;
|
||||
|
||||
// Frequency of the sine wave for testing.
|
||||
const frequency = 440;
|
||||
|
||||
audit.define(
|
||||
{
|
||||
label: 'interpolate',
|
||||
description: 'Interpolation of AudioBuffers to context sample rate'
|
||||
},
|
||||
(task, should) => {
|
||||
// The first channel is for the interpolated signal, and the second
|
||||
// channel is for the reference signal from an oscillator.
|
||||
let context = new OfflineAudioContext({
|
||||
numberOfChannels: 2,
|
||||
length: renderSamples,
|
||||
sampleRate: sampleRate
|
||||
});
|
||||
|
||||
let merger = new ChannelMergerNode(
|
||||
context, {numberOfChannels: context.destination.channelCount});
|
||||
merger.connect(context.destination);
|
||||
|
||||
// Create a set of AudioBuffers which are samples from a pure sine
|
||||
// wave with frequency |frequency|.
|
||||
const nBuffers = Math.floor(context.length / bufferLength);
|
||||
const omega = 2 * Math.PI * frequency / bufferRate;
|
||||
|
||||
let frameNumber = 0;
|
||||
let startTime = 0;
|
||||
|
||||
for (let k = 0; k < nBuffers; ++k) {
|
||||
// let buffer = context.createBuffer(1, bufferLength,
|
||||
// bufferRate);
|
||||
let buffer = new AudioBuffer(
|
||||
{length: bufferLength, sampleRate: bufferRate});
|
||||
let data = buffer.getChannelData(0);
|
||||
for (let n = 0; n < bufferLength; ++n) {
|
||||
data[n] = Math.sin(omega * frameNumber);
|
||||
++frameNumber;
|
||||
}
|
||||
// Create a source using this buffer and start it at the end of
|
||||
// the previous buffer.
|
||||
let src = new AudioBufferSourceNode(context, {buffer: buffer});
|
||||
|
||||
src.connect(merger, 0, 0);
|
||||
src.start(startTime);
|
||||
startTime += buffer.duration;
|
||||
}
|
||||
|
||||
// Create the reference sine signal using an oscillator.
|
||||
let osc = new OscillatorNode(
|
||||
context, {type: 'sine', frequency: frequency});
|
||||
osc.connect(merger, 0, 1);
|
||||
osc.start(0);
|
||||
|
||||
context.startRendering()
|
||||
.then(audioBuffer => {
|
||||
let actual = audioBuffer.getChannelData(0);
|
||||
let expected = audioBuffer.getChannelData(1);
|
||||
|
||||
should(actual, 'Interpolated sine wave')
|
||||
.beCloseToArray(expected, {absoluteThreshold: 9.0348e-2});
|
||||
|
||||
// Compute SNR between them.
|
||||
let snr = 10 * Math.log10(computeSNR(actual, expected));
|
||||
|
||||
should(snr, `SNR (${snr.toPrecision(4)} dB)`)
|
||||
.beGreaterThanOrEqualTo(37.17);
|
||||
})
|
||||
.then(() => task.done());
|
||||
});
|
||||
|
||||
audit.run();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -13,7 +13,9 @@
|
|||
window.onload = test.step_func(function() {
|
||||
var client = new XMLHttpRequest();
|
||||
var abortFired = false;
|
||||
var sync = true;
|
||||
client.onabort = test.step_func(function (e) {
|
||||
assert_false(sync);
|
||||
assert_equals(e.type, 'abort');
|
||||
abortFired = true;
|
||||
});
|
||||
|
@ -24,6 +26,7 @@
|
|||
test.done();
|
||||
}, 200);
|
||||
window.stop();
|
||||
sync = false;
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
|
|
|
@ -9,27 +9,69 @@
|
|||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
var test = async_test()
|
||||
test.step(function() {
|
||||
test(function(t) {
|
||||
var client = new XMLHttpRequest(),
|
||||
result = [],
|
||||
expected = [1, 4, 1] // open() -> 1,
|
||||
// abort() -> 4, open() -> 1
|
||||
client.onreadystatechange = function() {
|
||||
test.step(function() {
|
||||
result.push(client.readyState)
|
||||
})
|
||||
}
|
||||
expected = [
|
||||
'readystatechange', 0, 1, // open()
|
||||
'readystatechange', 2, 4, // abort()
|
||||
'abort', 2, 4, // abort()
|
||||
'loadend', 2, 4, // abort()
|
||||
'readystatechange', 3, 1, // open()
|
||||
]
|
||||
|
||||
var state = 0
|
||||
|
||||
client.onreadystatechange = t.step_func(function() {
|
||||
result.push('readystatechange', state, client.readyState)
|
||||
})
|
||||
client.onabort = t.step_func(function() {
|
||||
// abort event must be fired synchronously from abort().
|
||||
assert_equals(state, 2)
|
||||
|
||||
// readystatechange should be fired before abort.
|
||||
assert_array_equals(result, [
|
||||
'readystatechange', 0, 1, // open()
|
||||
'readystatechange', 2, 4, // abort()
|
||||
])
|
||||
|
||||
// readyState should be set to unsent (0) at the very end of abort(),
|
||||
// after this (and onloadend) is called.
|
||||
assert_equals(client.readyState, 4)
|
||||
|
||||
result.push('abort', state, client.readyState)
|
||||
})
|
||||
client.onloadend = t.step_func(function() {
|
||||
// abort event must be fired synchronously from abort().
|
||||
assert_equals(state, 2)
|
||||
|
||||
// readystatechange should be fired before abort.
|
||||
assert_array_equals(result, [
|
||||
'readystatechange', 0, 1, // open()
|
||||
'readystatechange', 2, 4, // abort()
|
||||
'abort', 2, 4, // abort()
|
||||
])
|
||||
|
||||
// readyState should be set to unsent (0) at the very end of abort(),
|
||||
// after this is called.
|
||||
assert_equals(client.readyState, 4)
|
||||
|
||||
result.push('loadend', state, client.readyState)
|
||||
})
|
||||
|
||||
client.open("GET", "resources/well-formed.xml")
|
||||
assert_equals(client.readyState, 1)
|
||||
|
||||
state = 1
|
||||
client.send(null)
|
||||
state = 2
|
||||
client.abort()
|
||||
assert_equals(client.readyState, 0)
|
||||
state = 3
|
||||
client.open("GET", "resources/well-formed.xml")
|
||||
assert_equals(client.readyState, 1)
|
||||
assert_array_equals(result, expected)
|
||||
})
|
||||
test.done()
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
43
tests/wpt/web-platform-tests/xhr/open-after-stop.window.js
Normal file
|
@ -0,0 +1,43 @@
|
|||
// window.stop() below prevents the load event from firing, so wait until it is
|
||||
// fired to start the test.
|
||||
setup({explicit_done: true });
|
||||
|
||||
onload = () => {
|
||||
async_test(function(t) {
|
||||
const client = new XMLHttpRequest();
|
||||
|
||||
const result = [];
|
||||
const expected = [
|
||||
'readystatechange', 0, 1, // open()
|
||||
];
|
||||
|
||||
let state = 0;
|
||||
|
||||
client.onreadystatechange = t.step_func(() => {
|
||||
result.push('readystatechange', state, client.readyState);
|
||||
});
|
||||
client.onabort = t.unreached_func("abort should not be fired after window.stop() and open()");
|
||||
client.onloadend = t.unreached_func("loadend should not be fired after window.stop() and open()");
|
||||
|
||||
client.open("GET", "resources/well-formed.xml");
|
||||
assert_equals(client.readyState, 1);
|
||||
|
||||
state = 1;
|
||||
client.send(null);
|
||||
state = 2;
|
||||
window.stop();
|
||||
// Unlike client.abort(), window.stop() does not change readyState
|
||||
// immediately, rather through a task...
|
||||
assert_equals(client.readyState, 1);
|
||||
state = 3;
|
||||
// ... which is then canceled when we open a new request anyway.
|
||||
client.open("GET", "resources/well-formed.xml");
|
||||
assert_equals(client.readyState, 1);
|
||||
assert_array_equals(result, expected);
|
||||
|
||||
// Give the abort and loadend events a chance to fire (erroneously) before
|
||||
// calling this a success.
|
||||
t.step_timeout(t.step_func_done(), 1000);
|
||||
}, "open() after window.stop()");
|
||||
done();
|
||||
};
|